C语言中的嵌套宏

C语言中,嵌套宏的用法。

嵌套宏的替换规则

C语言中,带参数的宏可以进行嵌套调用,如

1
2
3
4
5
#define f(a) #a
#define g() 42

// 嵌套调用
f(g())

嵌套调用涉及到一个参数展开的问题,因为参数也是宏定义,参数是先展开再替换,
还是不展开直接替换呢?

  • 如果宏定义中没有#或者##,则先展开参数再进行替换(跟嵌套的函数调用一样)
  • 否则,参数不展开而是直接替换

不论哪种情况,参数替换完成之后都会对替换之后的结果再次扫描,如果还有宏,
则再次重复这个过程。

注意:

  • #: 其后必须跟一个宏参数,它的作用是将其后的参数内容转换为字符串
  • ##: 它的作用是拼接两个符号,如1##2a##b,这两个符号不必是宏参数

需要注意的是,这两个符号在参数替换的时候起作用,而不会等到再次扫描阶段。

实例

来看一个实例,

1
2
3
4
5
6
7
8
#define f(a, b) a##b
#define g(a) #a, f(a, 0)
#define h(a) _##a, f(a, 0)
#define e(a) a

// 调用
g(e(1)) // "e(1)", 10
h(e(1)) // _e(1), 10

说明,

  • g(a): g的定义里面有#,所以参数不展开,直接替换(即所有的ae(1)来替换)
  • h(a): h的定义里面有##,所以参数也不展开,直接替换(即所有的ae(1)来替换)

替换完成之后会再次,者从f(a, 0)都被替换为10就可以得出。

(over)