Visual c++ Visual C和x2B之间宏##连接运算符的差异+;和海湾合作委员会

Visual c++ Visual C和x2B之间宏##连接运算符的差异+;和海湾合作委员会,visual-c++,gcc,c-preprocessor,stringification,Visual C++,Gcc,C Preprocessor,Stringification,我有一个这样的宏(不完全是这样,但函数相当等价): 这在Visual C++中是完美的,但是GCC 3.4.5(MIGGW)产生以下错误: 粘贴“.”和“项”不提供有效的预处理令牌 当我使用“->”操作符时也会发生这种情况。我没有发现关于连接的提示,即禁止使用这些运算符 有人有主意吗也许Visual C++将两个空间粘贴在一起,形成另一个空间。并不是说空白是标记,而是它允许您的代码工作 object.member不是一个令牌,它是三个令牌,因此不需要粘贴令牌来实现所描述的宏。只要去掉“##”,它

我有一个这样的宏(不完全是这样,但函数相当等价):

这在Visual C++中是完美的,但是GCC 3.4.5(MIGGW)产生以下错误:

粘贴“.”和“项”不提供有效的预处理令牌

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


有人有主意吗也许Visual C++将两个空间粘贴在一起,形成另一个空间。并不是说空白是标记,而是它允许您的代码工作

object.member
不是一个令牌,它是三个令牌,因此不需要粘贴令牌来实现所描述的宏。只要去掉“##”,它就可以在任何地方工作

[编辑:刚刚选中,使用##形成无效令牌的结果未定义。因此,据我所知,GCC可以拒绝它,MSVC可以忽略它,不执行粘贴。]

但是,不能将两个不在一起构成有效令牌的令牌粘贴在一起

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;
}
#包括
#定义STRUCTMEMBER(成员,值)全局结构状态。成员=值
结构{
常量字符*成员1;
}全球结构;
内部主(空)
{
STRUCTMEMBER(member1,“你好!”);
printf(“GlobalStructInstance.member1=%s\n”,
全球结构(成员1);
返回0;
}

根据C标准,“
##
”预处理运算符的结果必须是“预处理令牌”或结果未定义(C99 6.10.3.3(3)-#运算符)

预处理标记的列表是(C99 6.4(3)-词汇元素):

标题名称、标识符、预处理编号、字符常量、字符串文字、标点符号和单个非空白字符,这些字符在词汇上与其他预处理标记类别不匹配

GCC让您知道您正在进入未定义的领域。MSVC对未定义的结果(这是您非常期待的结果)默默地感到高兴


请注意,如果不创建单个令牌,则不需要令牌粘贴操作符。一般来说(我相信可能有一两个例外),2个由空格分隔的标记相当于2个不由空格分隔的标记-如您的示例中所示。

有任何用途吗?我已经阅读了gcc文档,因此他们解释了“删除所有空格”,所以我只是为了可读性而将它们放进去。我的第一个版本没有空格…谢谢,我不知道为什么,但当我以这种方式首次尝试时,它不起作用…正因为如此,我尝试了##操作符。。。现在看起来好多了!
#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;
}