宏定义中的"#"与“##”

定义

“#”是将宏字符串化(Stringification),“##”是将##左右两边的标签拼接在一起(## is called token concatenation, used to concatenate two tokens in a macro invocation)

例子

看一段代码

#include

#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int main()
{
printf("%s\n", h(f(1,2)));
printf("%s\n", g(f(1,2)));

return 0;
}

输出是:

12
f(1,2)

g(f(1,2))->stringification(f(,1,2))->f(1,2)
h(f(1,2))->h(1##2)->g(12)->#12->12

原因

在宏预扫描((macro prescan)阶段,宏参数首先会被替换,替换之后,再经过下次的扫描完成最后宏的展开(macro expand)。GCC在宏预处理阶段,特意加上了一条排外规则,那就是若宏参数被用于字符串化或者与其它标签连接,则不会被替代!下面是摘抄的一段预处理规则:

Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringized or pasted with other tokens. After substitution, the entire macro body, including the substituted arguments, is scanned again for macros to be expanded. The result is that the arguments are scanned twice to expand macro calls in them.

Reference

[1].https://stackoverflow.com/questions/6503586/what-does-in-a-define-mean
[2].http://blog.chinaunix.net/uid-27714502-id-3461678.html
[3]. https://www.2cto.com/kf/201303/195299.html
[4]. https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html

你可能感兴趣的:(C/C++)