C 语言 define 中的特殊操作符

C/C++学习笔记

# 操作符

字符串化操作符,将传入的参数名转换成带引号的字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
#define TOSTRING(str) #str

char s[] = TOSTRING(hello); // char s[] = "hello";
printf("%s\n", s); // hello

// 会忽略参数前后的空格
char s1[] = TOSTRING( hello ); // char s[] = "hello";
printf("%s, %d\n", s1, sizeof(s1)); // hello, 6

// 参数中字符中间有多个空格的时候会合并成一个空格
char s2[] = TOSTRING( hello world); // char s[] = "hello world";
printf("%s, %d\n", s2, sizeof(s2)); // hello world, 12

## 操作符

符号传递操作符,将多个参数合并成一个新的参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define NumberOne   1
#define NumberTwo 2

#define GETNUMBER(num) Number##num

int n;

n = GETNUMBER(One); // n = 1;
printf("%d\n", n); // 1

// define时会忽略 ## 前后的空格
#define GETNUMBER(num) Number ## num
n = GETNUMBER(Two); // n = 2;
printf("%d\n", n); // 2

// GetNumberX必须是编译器已知的宏定义,否则编译会报错
// error: ‘NumberThree’ undeclared (first use in this function);
n = GETNUMBER(Three); // n = NumberThree;

#define SSTRCAT(a, b) strcat(a##_p, #b);

char str1_p[20];
memset(str1_p, 0, 20);
char str2_p[20];
memset(str2_p, 0, 20);
strcat(str1_p, "111");
strcat(str2_p, "222");

SSTRCAT(str1, str2); // yes
// ## 展开只能进行一次 此处会报错
// 展开结果是 strcat(SSTRCAT(str1, str2), "str2");
// 而非 strcat(strcat(str1_p, "str2")_p, "str_2");
SSTRCAT(SSTRCAT(str1, str2), str2); // no

参考

cppreference

# Preprocessor Macro Operator

# and ## Operators in C