宏的展开规则替换最基本的替换规则,就是文本替换

带参数的宏宏可以带参数,并且在展开后使用这些参数

字符串化#可以将宏参数转化为字符串

连接运算符##可以将两个参数连接起来,变成一个新符号,注意不是字符串

在使用了#或##的宏中,如果宏的参数也是一个宏,则会阻止这个宏展开,为了保证参数宏优先展开,需要多嵌套一层宏

e.g:

12345678910111213#define Stringify(A) _Stringify(A)#define _Stringify(A) #A#define Concat(A, B) _Concat(A, B)#define _Concat(A, B) A##Bprintf("%s\n", Stringify(Concat(Hel, lo)));/* 展开顺序如下: Concat也是一个宏,并且是内层的,它被优先展开 1.Stringify(_Concat(Hel, lo)) # 注,如果Hel和lo也是宏的话,这一步也会展开 2.Stringify(Hello) 3."Hello"*/

嵌套宏展开宏展开时会递归的展开嵌套的宏定义

当预处理器遇到一个宏调用时,它会用宏定义的内容替换宏调用

对于参数化的宏,预处理器会尝试用传递的参数替换掉宏定义中的参数

默认情况下,宏参数的替换是立刻发生的,在展开过程中,遇到该宏名时参数首先被替换,然后宏体会被继续展开

在展开一个宏时,如果参数本身也是宏,通常会进一步展开

展开内层宏参数,再展开外层宏参数

如果某个形参前面有#运算符,那么先不展开该形参对应的实参,而是直接把这个实参变为字符串

如果某个形参前面有#@,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符

如果某个形参前面或后面有##,则调用此宏定义时,不展开该形参对应得实参,而是将该运算符前后都实参连接起来作为一个新符号