【问题标题】:About ## preprocessor in C关于 C 中的## 预处理器
【发布时间】:2012-06-14 16:13:35
【问题描述】:

给定

#define cat(x,y) x##y

调用cat(a,1) 返回a1,但cat(cat(1,2),3) 未定义。 但是,如果我还定义了#define xcat(x,y) cat(x,y),那么xcat(xcat(1,2),3) 的结果现在是123。谁能详细解释一下为什么会这样?

【问题讨论】:

  • 你的意思是then the result of xcat(xcat(1,2),3) is now 123
  • @notfed:对不起,我写错了。是的 xcat(xcat(1,2),3) 的结果是 123

标签: c-preprocessor


【解决方案1】:

我使用 GCC 和 Clang 对此进行了测试。

GCC 给出错误:

test.c:6:1: error: pasting ")" and "3" does not give a valid preprocessing token

Clang 给出错误:

test.c:6:11: error: pasting formed ')3', an invalid preprocessing token
  int b = cat(cat(1,2),3);

似乎正在发生的事情是编译器将cat(1,2) 的结果在展开后立即用括号括起来;因此,当您在代码中调用 cat(1,2) 时,它确实为您提供了 (12)。然后,再次调用cat((12),3) 会导致((12)3),这不是一个有效的令牌,这会导致编译错误。

普遍的看法是“当使用标记粘贴操作符 (##) 时,你应该使用两级间接”(即,使用你的 xcat 解决方法)。请参阅Why do I need double layer of indirection for macros?What should be done with macros that need to paste two tokens together?

【讨论】:

  • 在我的问题中,用 cat(x,y) 替换 xcat(x,y) 后它再次变为 cat(cat(1,2),3) 然后即使现在它也应该返回无效令牌。我无法理解这两个间接级别是如何工作的。我阅读了上面的网址,但对我来说仍然不是很清楚。
【解决方案2】:

在 xcat(x,y) 中,x 和 y 与 ## 运算符不相邻,并且 因此它们在被替换之前会进行宏扩展。

所以 x 被识别为 xcat(1,2) 并且 y 被识别为 3。但先验 为了替换,x 被宏扩展为 cat(1,2),变成 1##2 变成 12。所以最终, xcat(xcat(1,2),3) 将扩展 到 cat(12,3),结果是 123。

这项工作 --> cat(xcat(1,2),3) --> cat(cat(1,2),3) --> cat(12,3)

行为是明确定义的,因为所有标记粘贴 产生有效的预处理器标记,即任何扩展的 xpression 在任何阶段都应该是有效的标记。

【讨论】:

  • 好吧,你的例子不起作用,但xcat(cat(1,2),3) 还是起作用了。
【解决方案3】:

我不认为 cat 是否真的会连续扩展 2 次。这就是为什么我想知道为什么编译器甚至会产生像'pasting ")" and "3" does not give a valid preprocessing token' 这样的消息。 另外,我不认为内心的猫会首先被扩大。所以,我假设输出是cat(1,2)3。这引导我思考编译器将如何解释这个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 2011-07-02
    相关资源
    最近更新 更多