奇怪的C ++预处理器宏语法

时间:2010-08-01 17:43:21

标签: c++ concatenation c-preprocessor

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

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

#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

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

3 个答案:

答案 0 :(得分:9)

请改用:

#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
}

答案 1 :(得分:2)

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

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

这应该可以为您提供Luther解决方案工作原理的线索,而您的解决方案则不然。

答案 2 :(得分:1)

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