我有一个这样的宏(不完全是,但功能相当):
#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);
这在Visual C ++中完美运行,但是gcc 3.4.5(MingGW)会产生以下错误:
粘贴“。”并且“Item”不提供有效的预处理令牌
当我使用“ - >”时也会发生这种情况运营商。我没有找到关于连接的提示,禁止使用这些运算符。
有没有人有想法?
答案 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)
但是,两个不能一起形成有效令牌的令牌无法粘贴在一起。
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;
}