宏的展开规则

宏的展开规则

替换

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

带参数的宏

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

字符串化

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

连接运算符

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

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

e.g:

1
2
3
4
5
6
7
8
9
10
11
12
13
#define Stringify(A) _Stringify(A)
#define _Stringify(A) #A

#define Concat(A, B) _Concat(A, B)
#define _Concat(A, B) A##B

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

嵌套宏展开

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

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

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

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

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

  1. 展开内层宏参数,再展开外层宏参数
  2. 如果某个形参前面有#运算符,那么先不展开该形参对应的实参,而是直接把这个实参变为字符串
  3. 如果某个形参前面有#@,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符
  4. 如果某个形参前面或后面有##,则调用此宏定义时,不展开该形参对应得实参,而是将该运算符前后都实参连接起来作为一个新符号

宏的展开规则
https://yill-z.github.io/2025/01/15/宏的展开规则/
作者
Yill Zhang
发布于
2025年1月15日
许可协议