#include <stdio.h>
#define f(a,b) printf("yes")
#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)));
}
有人可以解释为什么两个printf()语句的输出都不同。
答案 0 :(得分:15)
由于预处理器执行操作的顺序,输出不同,这在C99标准的6.10.3节(及其后续节)中有所描述。特别是这句话来自6.10.3.1/1:
替换列表中的参数,除非前面有
#
或##
预处理标记或后跟##
预处理标记,否则在其中包含所有宏后,将替换为相应的参数已经扩大了。
所以在第一行中,当扩展h
的调用时,参数f(1,2)
在之前展开,它取代了h
的参数{{1 }}。 a
仅在稍后重新扫描所有内容的输出时看到#
的调用时才会发挥作用。
但是在第二行,g
被立即看到,上面引文的“除非前面......”条款触发了不同的行为。
答案 1 :(得分:8)
预处理器完成宏扩展后,编译器会看到:
int main()
{
printf("%s\n","printf(\"yes\")");
printf("%s\n","f(1,2)");
}
这是一种常见的技术,可以在“额外”间接中进行分层,以控制何时获得字符串化以及何时获得实际的宏评估。
基本上,宏观评估是从“外部”发生的,而不是相反。 wikipedia page表示“参数不会先解析为宏替换”,我认为这是指相同的事情。