【问题标题】:Weird C++ preprocessor macro syntax奇怪的 C++ 预处理器宏语法
【发布时间】:2011-03-23 22:07:14
【问题描述】:

我已经将我的问题提炼为这段代码 sn-p - 但它是一个更大程序的一部分,所以我不想要一种不同的方式来做到这一点 - 我需要一种方法来制作 这个 工作!

当我从此代码生成预处理文件时:

#define OUTER(a, b) \
    a##b
#define INNER(c, d) \
    c##d

enum foo {
    OUTER(INNER(x, y), z)
}; // line 108

int APIENTRY _tWinMain(...)
{
    foo bar = xyz; // line 112
}

我明白了:

enum foo {
    xyz
}; // line 108

int __stdcall wWinMain(...)
{
    foo bar = xyz; // line 112
}

这就是我想要的。但是,如果我尝试编译我得到的代码:

错误 C2146:语法错误:在标识符“z”第 108 行之前缺少“}”
错误 C2143:语法错误:缺少“;”在“}”第 108 行之前
错误 C2143:语法错误:缺少“;”在“}”第 108 行之前
错误 C2059:语法错误:'}' 第 108 行
错误 C2065:“xyz”:未声明的标识符第 112 行

我做不出来!问题似乎是由## 引起的:

#define OUTER(a, b) \
    a##b

但是为什么(以及如何解决它)超出了我的范围......

【问题讨论】:

  • @Jack 你能解释一下 a##b 应该做什么吗?以前从未见过。
  • @Insert 这是一个预处理器操作符,它实际上连接了它的两个参数。例如,OP 代码 sn-p 中的OUTER(test, string) 被预处理器替换为teststring
  • 好吧,我可以确认这也发生在 gcc 中,而且他们的错误更具描述性。就是说不能把)z粘贴在一起。在我看来,预处理器不能像这样进行嵌套粘贴,但目前这是猜测。希望对您有所帮助..
  • @InsertNickHere 这是标记连接,是任何 C 预处理器的一部分。 en.wikipedia.org/wiki/C_preprocessor#Token_concatenation
  • 您能提供一个更真实的用法或宏示例吗?现在,宏基本上没用。

标签: c++ concatenation c-preprocessor


【解决方案1】:

改用这个:

#define CONCAT(X,Y) X##Y
#define OUTER(a, b) CONCAT(a,b)
#define INNER(a, b) CONCAT(a,b)

enum foo {
    OUTER(INNER(x, y),z)
}; // line 108

int main(...)
{
    foo bar = xyz; // line 112
}

【讨论】:

  • 哇哦,它有效!但是你能向我解释为什么它有效吗?为什么我的预处理输出正确​​?我从下面描述的 gcc 错误中看到它似乎保留了“)”并试图将“z”连接到“xy)”?但这并没有出现在我的预处理输出中!
  • 阅读 Jonathan Leffler 的规范答案:stackoverflow.com/questions/1489932/…
  • 啊! OUTER 是不是像我想的那样得到“INNER(c,d),z”而不是“xy,z”?这是有道理的。但我仍然不明白为什么我的预处理输出是正确的!
  • 无需声明两个单独的 OUTER/INNER 宏,这也可以:OUTER(OUTER(x, y),z)
【解决方案2】:

使用gcc 预处理您的示例会导致:

enum foo {
t.c:7:1: error: pasting ")" and "z" does not give a valid preprocessing token
    xy z
};

这应该可以让您了解为什么 Luther 的解决方案有效而您的解决方案无效。

【讨论】:

    【解决方案3】:

    如果你使用 gcc,那么你可以给它 -E 选项来查看预处理的输出。然后您可以轻松查看预处理器的输出以及如何进一步调试宏。其他编译器也有类似的选项。

    【讨论】:

      猜你喜欢
      • 2016-09-16
      • 2016-08-26
      • 2010-11-24
      • 2023-03-10
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多