2009-07-30 91 views
5

我有这样一个宏(不完全,但功能还是相当相当)GCC宏##连接符:差异在Visual-C++和

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

这工作完全在Visual C++,但gcc 3.4.5(MingGW)产生以下错误:

pasting "." and "Item" does not give a valid preprocessing token

这也发生在我使用“ - >”运算符时。我没有发现关于连接的提示,这些操作符的使用是被禁止的。

有没有人有想法?

+1

http://gcc.gnu.org/ml/gcc-help/2003-04/msg00213.html有什么用? – AakashM 2009-07-30 13:33:07

+0

空间故意? – EFraim 2009-07-30 13:33:29

回答

7

也许Visual C++将两个空间粘贴在一起以创建另一个空间。不是空格是令牌,但它可以让你的代码工作。

object.member不是一个标记,它是三个标记,所以你不需要标记粘贴来实现你描述的宏。只要删除'##',它应该无处不在。

[编辑:刚刚检查,并且使用##形成非有效标记的结果未定义。所以GCC允许拒绝和MSVC允许忽略它并没有进行粘贴,据我可以告诉]

4

gcc c preprocessor docs

However, two tokens that don't together form a valid token cannot be pasted together.

structure.member不是一个单一的令牌。

在这种情况下,您不需要使用##(令牌串联)运算符。你可以删除它。下面是一个例子用gcc 4.2.4在Linux上进行了测试:

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

按照C标准中,“##”预处理运算的结果必须是“预处理记号”或结果是未定义的(C99 6.10 .3.3(3) - ##运算符)。

预处理标记的名单(C99 6.4(3) - 词法元素):

header names, identifiers, preprocessing numbers, character constants, string literals, punctuators, and single non-white-space characters that do not lexically match the other preprocessing token categories.

GCC可以让你知道你正在进入不确定的领土。 MSVC对未定义的结果非常满意(这就是你期望发生的事情)。

请注意,如果您还没有创建单个令牌,那么您不需要令牌粘贴操作符。通常(我确定可能有一个例外或两个),用空格分隔的2个令牌相当于2个未被空格分隔的令牌 - 就像你的例子。