(1)#
在一个宏中的参数前面使用一个#, 预处理器会把这个参数转换为一个字符数组
简化理解:#是“字符串化”的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串
例如代码:
#define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")
则:
ERROR_LOG("add"); 转换为 fprintf(stderr,"error: "add"\n");
ERROR_LOG(devied =0); 转换为 fprintf(stderr,"error: devied=0\n");
(2)##, “##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接,称为“记号粘合”。
在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些##来替代空格。
例如代码:
#define A1(name, type) type name_##type##_type
#define A2(name, type) type name##_##type##_type
则:
A1(a1, int); /*等价于: int name_int_type; */
A2(a1, int); /*等价于: int a1_int_type; */
解释:
1)在第一个宏定义中,"name"和第一个"_"之间,以及第2个"_"和第二个"type"之间没有被分隔,所以预处理器会把name_##type##_type解释成3段:“name_”、“type”、以及“_type”,这中间只有“type”是在宏前面出现过的,所以它可以被宏替换。
2)而在第二个宏定义中,“name”和第一个“_”之间也被分隔了,所以预处理器会把name##_##type##_type解释成4段:“name”、“_”、“type”以及“_type”,这其间,就有两个可以被宏替换了。
(3)延伸
#define A(x) T_##x #define B(x) #@x #define C(x) #x
我们假设:x=1,则有:
A(1) ------〉T_1
B(1) ------〉'1'
C(1) ------〉"1"