我有一个关于' ##'的问题用于使用解除引用运算符进行预处理器粘贴。谁能告诉我为什么下面的代码不能编译?
typedef struct
{
char data;
} MY_STRUCT;
MY_STRUCT My_Instance;
MY_STRUCT* My_PInstance;
#if 1
#define GET_MEMBER(membername) (My_PInstance->##membername)
#else
#define GET_MEMBER(membername) (My_Instance.##membername)
#endif
然后我打电话:
char value = GET_MEMBER(data); // Where My_PInstance is properly instantiated.
我收到编译错误。
error: pasting "->" and "data" does not give a valid preprocessing token
答案 0 :(得分:5)
您无需粘贴。
只需(My_Pinstance->membername)
'##'应将两个令牌粘贴到一个有效令牌中。然而
->foo
无效令牌。 (例如foo)
答案 1 :(得分:2)
对于任何以这种方式来的人。我有同样的问题,但是'。'未讨论的GET_MEMBER(..)宏的变体,但我认为问题是相同的。
我犹豫地接受了cwyang的回答,因为真正被粘贴的是文字
My_PInstance->
与
data
用 - 我的(和用户......)思考 - 结果是一个合适的标记。
My_PInstance->data
所以,我坚持通过更多的谷歌搜索结果。最后我来到this guy,他给出了一个真正的打击历史记录。总结:
曼。这家伙说没有希望......
哎呀,到底是什么?我去了那儿。替代语法有效,我使用古老的编译器 几乎 !g++ (GCC) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
所以,对于所有你勇敢的字符串化器和连接符和标记符(!),这是我的教训。
之前:
#define PROFILING_START_CLK(STAT, n) \
time0##STAT##n = PRF_CLK_FN(); \
profilingStatsIndex##STAT##n = STAT##.count % PROFILE_SIZE; \
STAT#.count++;
这样称呼:
PROFILING_START_CLK(tst, 0);
为每个使用的地方返回以下错误的2个内容:
error: pasting "tst" and "." does not give a valid preprocessing token
就像user1159503一样。
继续前进...... 以下作品:
#define PROFILING_START_CLK(STAT, n) \
time0##STAT##n = PRF_CLK_FN(); \
profilingStatsIndex##STAT##n = STAT/**/.count % PROFILE_SIZE;\
---------------------------------------^^^^
STAT/**/.count++;
--------^^^^
无论是否使用g ++ -ansi开关,前/后版本都失败/编译。
它起作用的原因是因为预处理器在进入宏之前删除了注释,所以顺序是这样的。
'##'应该在宏中组合任意结构和/或成员吗?我不知道。我会这么认为,但对于不跨越运营商的粘贴过程来说似乎也是正确的。
否则,问题是,“粘贴过程是否合理只是”加入“像我们在这里谈论的那样的运营商。('。',' - >','::',.. ..)“