3

atest.c

#define COMMENT /##/

int main()
{
   ...
   COMMENT int atest;
   ...
}

错误消息:

atest.c:16:1: error: pasting "/" and "/" does not give a valid preprocessing token

atest.c: In function 'main':

atest.c:16: error: expected expression before '/' token

虽然 Microsoft C 编译器对 COMMENT 宏很满意。这里的提示也不起作用。

有人可以为此提供解决方案或解释吗?谢谢。

4

3 回答 3

8

当您使用标记粘贴运算符##时,组合两个操作数的结果必须是有效的预处理器标记。

//不是有效的预处理令牌。删除评论后进行预处理,因此无法在预处理阶段添加评论。

于 2012-06-03T08:40:36.210 回答
4

因为注释处理是在宏之前完成的,所以宏生成的注释不能被编译器识别。引用 Ben Combee 对您引用的文章的回应:

我刚刚阅读了您在 2001 年 1 月号的 CUJ 上发表的 C/C++ Tip #5。提示的内容(执行扩展为注释的宏)非常熟悉,因为我在 Microsoft 的一个头文件中看到了类似的方法。但是,提示是非常不正确的。

作者使用标记粘贴来构造评论开始序列。但是,根据 C 和 C++ 标准,这是无效的。在 ISO C (1999) 的第 5.1.1.2 节中,标题为“翻译阶段”,注释处理发生在第 3 阶段,预处理器识别标记和空格,注释替换为空格。然后在第 4 阶段完成宏处理,该阶段将引入这些新的注释开始序列。在 #4 之后没有后续阶段可以识别注释,因此最终符合标准的编译器会由于非法标记 - '//' 而拒绝程序文本。1998 C++ 标准在第 2.1 节“翻译阶段 [lex.phases]”中有类似的语言。

一些编译器充分混合了阶段的顺序和处理以允许该宏工作,Microsoft 的 Visual C++ 6.0 以其受欢迎程度而著称。其他的,例如 Metrowerks CodeWarrior C/C++ 编译器(在我目前的工作之前,我曾作为编译器工程师工作了两年多)遵循标准并且将拒绝提示中显示的用法。

谢谢,

Ben Combee 首席软件架构师 Veriprise Wireless http://www.veriprise.com

因此,发布此通知的期刊:

因此,我们想提醒读者,这个技巧是不可移植的,可能不应该在生产代码中使用。

于 2012-06-03T08:38:43.880 回答
2

很抱歉,我没有关于如何执行此操作的答案。

您可以使用命令 cpp(c prepocessor)来预处理您的代码并查看发生了什么。通过 cpp 运行您提供的代码会得到以下结果:

int main()
{
a.c:5:1: error: pasting "/" and "/" does not give a valid preprocessing token
       / / int atest;
}

#define COMMENT /
#define SLASH(x) x/

SLASH(COMMENT)

结果是

/ /

然而尝试

#define TEST(y) y/
TEST(hello)

结果是

hello/

通常,诸如 // 之类的注释会被删除并替换为单个“注释标记”,这一步是在预处理之前完成的(当 # 指令发生时),因此即使你可以在那里得到你的评论,我怀疑它总是认可(AFAIK 标准不保证它)。

很抱歉,我无法提供更多帮助。

于 2012-06-03T08:38:49.493 回答