我试图了解C ++标准预处理器要求。我创建的一个有点棘手的例子在GCC和VC ++ 2010中有令人惊讶的结果:
#define a(x,y) x##y
#define tzsW kka
a(t,zs )W
GCC收益率:
tzs W
请注意在W之前添加的额外空间。
VC ++ 2010收益率:
tzsW
请注意,在W之前没有添加空格,但标识符不会进一步扩展。我通过C ++ 03标准进行了扫描,无法找到任何说明我们应该阻止在gcc中创建新标识符(tzsW
)的内容。而且没有任何事情可以阻止这个新标识符进一步扩展宏(VC ++行为)。
为什么GCC和VC ++ 2010不喜欢新的标识符?
修改
如果使用了另一个宏调用,例如
a(t,zs )[]
gcc产量:
tzs[]
注意没有添加空格,显示gcc故意为我以前的情况添加空间。
答案 0 :(得分:4)
预处理器的输出是标记,而不是纯文本。除非您使用令牌粘贴运算符,否则通常不会在预处理中组合令牌。
查看预处理步骤的输出时,必须将标记转换为文本。 gcc会插入空格,因此您不会误以为tzsW
是单个标记。它不需要在tzs[
情况下执行此操作,因为[
不是有效的标识符字符,因此不会产生混淆。
两个编译器都没有将tzsW
视为要重新扩展的单个令牌。
请注意,Visual C++ documentation确认编译预处理器的输出与编译原始源相比可能会产生不同且不正确的输出,因为它们在转换预处理输出时不插入空格来分隔标记到文本。当预处理器输出在正常操作中直接传递到编译器的下一个阶段时,不会发生这种情况。
答案 1 :(得分:1)
空间还是空间?
我没有在标准中找到参考,但是this article讨论了这个问题。简而言之,要判断你是否想要这个空间并不容易......
用tzsW
替换kka
?
见标准中的16.3.4:
替换列表中的所有参数都被替换后, 生成的预处理标记序列将全部重新扫描 后续预处理源文件的标记以获得更多宏 要替换的名称。
这表明此处VC的行为不正确。