宏评估订单

Utk*_*tav 13 c c++ macros c-preprocessor

可能重复:
宏中的#和##

为什么第二个printf的输出是f(1,2)宏的评估顺序是什么?

#include <stdio.h>
#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;
}

output 12 
       f(1,2)
Run Code Online (Sandbox Code Playgroud)

Pub*_*bby 18

来自http://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html#Argument-Prescan

宏参数在被替换为宏体之前完全是宏扩展的,除非它们被字符串化或粘贴到其他标记.替换后,将再次扫描整个宏体(包括替换参数),以便扩展宏.结果是参数被扫描两次以扩展其中的宏调用.

含义:

  • f连接其参数,因此其参数不会扩展
  • h不会对其参数进行字符串化或连接,因此它的参数会被扩展.
  • g字符串化其参数,因此其参数不会扩展

h(f(1,2)) -> g(12) -> "12"

g(f(1,2)) -> "f(1,2)"


Jam*_*lis 7

参数在替换到替换列表之前被宏替换,除非它作为#(stringize)或##(concatenate)的操作数出现.

在您的宏中h,参数a不是这两个运算符之一的参数,因此参数被宏替换,然后替换为替换列表.也就是说,参数f(1,2)是宏被替换为1##2,然后到12,然后它被替换成g(12),这是(再次)宏替换成为"12".

当你g直接调用时,参数a 是#运算符的参数,因此它的参数在替换之前不会被宏替换: f(1,2)直接替换到替换列表中,屈服"f(1,2)".