c编程语言中的宏评估

时间:2010-09-23 08:56:23

标签: c macros

  

可能重复:
  What does “#define STR(a) #a” do?

#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()语句的输出都不同。

2 个答案:

答案 0 :(得分:15)

由于预处理器执行操作的顺序,输出不同,这在C99标准的6.10.3节(及其后续节)中有所描述。特别是这句话来自6.10.3.1/1:

  

替换列表中的参数,除非前面有###预处理标记或后跟##预处理标记,否则在其中包含所有宏后,将替换为相应的参数已经扩大了。

所以在第一行中,当扩展h的调用时,参数f(1,2)之前展开,它取代了h的参数{{1 }}。 a仅在稍后重新扫描所有内容的输出时看到#的调用时才会发挥作用。

但是在第二行,g被立即看到,上面引文的“除非前面......”条款触发了不同的行为。

另见the relevant C-FAQ entry

答案 1 :(得分:8)

预处理器完成宏扩展后,编译器会看到:

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

这是一种常见的技术,可以在“额外”间接中进行分层,以控制何时获得字符串化以及何时获得实际的宏评估。

基本上,宏观评估是从“外部”发生的,而不是相反。 wikipedia page表示“参数不会先解析为宏替换”,我认为这是指相同的事情。