嵌套调用中##运算符的行为

时间:2014-06-21 12:12:52

标签: c c-preprocessor

我正在读一本关于C编程语言的书,我发现:

#define cat(x,y) x##y
#define xcat(x,y) cat(x,y)

调用cat(cat(1,2),3)会产生错误,而调用xcat(xcat(1,2),3)会产生预期结果123

两者的工作方式有何不同?

1 个答案:

答案 0 :(得分:5)

替换列表取决于##的宏通常无法以嵌套方式调用。
cat(cat(1,2),3)未按正常方式展开,cat(1,2)产生12,然后cat(12, 3)产生123
替换列表中##之前或之后的宏参数在替换时不会被扩展。

6.10.3.1参数替换

  

1在确定了调用类函数宏的参数之后,   参数替换发生。替换列表中的参数,除非在前面   通过###预处理令牌或后跟##预处理令牌(见下文),在其中包含的所有宏之后被相应的参数替换   扩大。在被替换之前,每个参数的预处理标记都是   完全宏被替换,好像它们形成了预处理文件的其余部分;没有其他   预处理令牌可用。

因此,cat(cat(1,2),3)会扩展为cat(1,2)3,因为没有名为cat(1,2)3的宏,所以#define xcat(x,y) cat(x,y) 无法进一步扩展。

以防

xcat(xcat(1,2),3)
写作xcat将起作用。当预处理器扩展xcat(1,2)的外部调用时,它也会扩展xcat;区别在于 ##的替换列表不再包含xcat(xcat(1,2),3) ==> cat(12, 3) ==> 12##3 ==> 123

{{1}}