首页 文章

GCC和VC预处理器的意外行为

提问于
浏览
1

我试图了解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故意为我以前的情况添加空间 .

2 回答

  • 4

    预处理器的输出是令牌,而不是纯文本 . 除非您使用令牌粘贴运算符,否则通常不会将令牌组合在预处理中 .

    查看预处理步骤的输出时,必须将标记转换为文本 . gcc插入空格,这样你就不会误以为 tzsW 是一个令牌 . 它不需要在 tzs[ 情况下执行此操作,因为 [ isn 't a valid identifier character so there'没有混淆 .

    两个编译器都没有将 tzsW 视为要重新扩展的单个令牌 .

    请注意Visual C++ documentation确认编译预处理器的输出可能会产生与编译原始源相比不同且不正确的输出,因为当预处理器输出直接传递到编译器的下一级时,它们不会发生操作 .

  • 1
    • 空间还是没有空间?

    我没有在标准中找到参考,但this article讨论了这个问题 . 简而言之,要判断你是否想要这个空间并不容易......

    • kka 代替 tzsW

    见标准中的16.3.4:

    替换替换列表中的所有参数后,将使用源文件的所有后续预处理标记重新扫描生成的预处理标记序列,以替换更多的宏名称 .

    这表明VC的行为在这里不正确 .

相关问题