代码:
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
main()
{
printf("%s\n",h(f(1,2))); //[case 1]
printf("%s\n",g(f(1,2))); //[case 2]
}
输出:
12
f(1, 2)
为什么两种情况下的输出都不相同?
[我理解连接(a##b
)和字符串转换(#a
)here,但我不明白为什么输出在两种情况下都不同。] < / em>的
答案 0 :(得分:6)
规范的相关部分是:
6.10.3.1
“在确定了调用类函数宏的参数之后, 参数替换发生。替换列表中的参数,除非在前面 通过#或##预处理令牌或后跟##预处理令牌(见下文),是 在其中包含的所有宏之后用相应的参数替换 扩大“。
换句话说,当替换宏参数时,首先在参数上有一轮宏扩展,除非参数出现#或##。
所以g(blah)
只是将blah
字符串化。 h(blah)
首先进行宏扩展blah
,然后将其字符串化。
当您想要对宏名称进行字符串化时,差异尤为重要:
printf("The value of the " g(NULL) " macro is " h(NULL));
答案 1 :(得分:1)
这可能是评估的顺序。在第一种情况下,h和f在第一次传递到g和12时得到评估。宏评估的第二次传递然后将其转换为12.在第二种情况下,g直接将f(1,2)计算为字符串。
答案 2 :(得分:1)
当扩展函数样式宏时,替换列表中不以#
开头或紧邻##
的任何参数实例在宏扩展后被相应的参数替换。对于#
之后或与##
相邻的参数,不会发生宏扩展。如果扩展中还有任何宏,则在替换时会递归宏扩展,直到没有剩余的宏为止。 (任何宏的扩展在任何嵌套级别的扩展期间都不会自行扩展,因此无法获得任何无限递归。)
在您的示例中,g(f(1,2))
变为#
f(1,2)
(不扩展宏参数),即“f(1,2)”,字符串文字。
h(f(1,2))
变为g( 12 )
因为f(1,2)
经历了宏扩展,此扩展中有剩余的宏,因此会再次展开,g( 12 )
变为“12”。 / p>
答案 3 :(得分:0)
C宏不是函数。这是简单的文本替换。只需将g(a)中的 a 替换为“f(1,2)”,这就是你的答案。