我遇到了一段更令人困惑的代码......
#include "stdio.h"
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main(void)
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(1));
printf("%s\n",g(f(1,2)));
return 0;
}
输出
12
1
f(1,2)
我的假设是
1)由于宏f(1,2)
,第一个12
被f(a,b)
取代
证实其论点
2)然后g(a)
宏用字符串文字1
替换"1"
3)输出应为1
但为什么g(f(1,2))
没有被12
取代。
我确定我在这里遗漏了一些东西。
有人能解释一下这个程序吗?
答案 0 :(得分:2)
宏替换从外部发生。(严格地说,预处理器的行为就好像它一次替换一个宏,从文件的开头开始,并在每次替换后重新启动。)
标准(C99§6.10.3.2/ 2)说
如果在替换列表中,参数前面紧跟
#
预处理 令牌,两者都被单个字符串文字预处理令牌所取代 包含相应的预处理标记序列的拼写 参数。
由于#
存在于宏g
的替换列表中,因此参数f(1,2)
会立即转换为字符串,结果为{ {1}}。
另一方面,在"f(1,2)"
中,由于替换列表不包含h(f(1,2))
,因此适用§6.10.3.1/ 1,
在确定了调用类函数宏的参数之后, 参数替换发生。替换列表中的参数,除非在前面 通过
#
或#
预处理令牌或后跟##
预处理令牌(见下文), 在其中包含的所有宏之后用相应的参数替换 扩大。
并且参数##
已展开宏以提供f(1, 2)
,因此结果为12
,当文件被“重新扫描”时,结果变为g(12)
。< / p>
答案 1 :(得分:1)
宏无法扩展到预处理指令。从C99 6.10.3.4/3“重新扫描和进一步更换”:
由此产生的完全宏替换的预处理标记序列 即使它类似,也不会被处理为预处理指令 一个,
来源:https://stackoverflow.com/a/2429368/2591612
但您可以像f(a,b)
一样从g
拨打h
。 f(a,b)
被解释为字符串文字为@Red Alert个状态。