宏“#define STR(x)#x”和“#define STR(x)VAL(x)”与“#define VAL(x)#x”之间有什么区别?

当我使用这段代码时:

#include  #define STR(x) #x int main(void) { printf(__FILE__ STR(__LINE__) "hello!\n"); return 0; } 

它打印

 hello.c__LINE__hello! 

但是当我使用它时:

 #include  #define STR(x) VAL(x) #define VAL(x) #x int main(void) { printf(__FILE__ STR(__LINE__) "hello!\n"); return 0; } 

它打印

 hello.c7hello! 

有什么区别

 #define STR(x) #x 

 #define STR(x) VAL(x) #define VAL(x) #x 

宏的参数本身是宏扩展的, 除非宏参数名称出现在带有stringifier#或token-paster ##的宏体中。

在第一种情况下,STR的参数不是宏扩展的,因此您只需获取LINE宏的名称。

在第二种情况下,当STR被转换为VAL的定义时,STR的参数宏扩展的,因此它可以工作 – 你得到实际的行号,因为LINE宏被扩展了。

C99 N1256标准草案 6.10.3.1/1“参数替换”:

在确定了调用类函数宏的参数之后,发生了参数替换。 替换列表中的参数,除非前面带有#或##预处理标记或后跟##预处理标记(见下文),否则在扩展其中包含的所有宏之后,相应的参数将替换该参数。 在被替换之前,每个参数的预处理标记都被完全宏替换,好像它们形成了预处理文件的其余部分; 没有其他预处理令牌可用。

所以###使参数得到不同的对待。