Visual C ++和gcc之间的宏##连接运算符的差异

时间:2009-07-30 13:30:36

标签: visual-c++ gcc c-preprocessor stringification

我有一个这样的宏(不完全是,但功能相当):

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);

这在Visual C ++中完美运行,但是gcc 3.4.5(MingGW)会产生以下错误:

  

粘贴“。”并且“Item”不提供有效的预处理令牌

当我使用“ - >”时也会发生这种情况运营商。我没有找到关于连接的提示,禁止使用这些运算符。

有没有人有想法?

3 个答案:

答案 0 :(得分:7)

也许Visual C ++将几个空格粘在一起以形成另一个空间。并不是说空格是令牌,而是允许你的代码工作。

object.member不是令牌,它是三个令牌,因此您不需要使用令牌粘贴来实现您描述的宏。只需删除'##'即可在任何地方使用。

[编辑:刚检查过,使用##形成非有效令牌的结果是未定义的。因此,据我所知,GCC被允许拒绝它,并且允许MSVC忽略它并且不执行粘贴。]

答案 1 :(得分:5)

根据C标准,'##'预处理运算符的结果必须是'预处理标记'或结果未定义(C99 6.10.3.3(3) - ##运算符)。< / p>

预处理令牌列表是(C99 6.4(3) - 词汇元素):

  

标题名称,标识符,预处理数字,字符常量,字符串文字,标点符号以及不与其他预处理标记类别词汇匹配的单个非空白字符。

GCC让您知道您正在输入未定义的区域。 MSVC默默地对未定义的结果感到满意(这是你非常希望发生的事情)。

请注意,如果您还没有创建单个令牌,那么您不需要令牌粘贴操作符。一般来说(我确定可能有一两个异常),用空格分隔的2个令牌相当于2个用空格分隔的令牌 - 如你的例子所示。

答案 2 :(得分:4)

来自gcc c preprocessor docs

  

但是,两个不能一起形成有效令牌的令牌无法粘贴在一起。

structure.member不是单个令牌。

在这种情况下,您不需要使用##(标记连接)运算符。你可以删除它。以下是在linux上使用gcc 4.2.4测试的示例:

#include <stdio.h>

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value

struct {
    const char* member1;
}GlobalStructInstance;

int main(void)
{

    STRUCTMEMBER(member1, "Hello!");

    printf("GlobalStructInstance.member1 = %s\n",
           GlobalStructInstance.member1);

    return 0;
}