【问题标题】:Single line comment macro chokes gcc单行注释宏阻塞 gcc
【发布时间】:2012-06-03 08:17:41
【问题描述】:

test.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 宏很满意。 here的小费也不行。

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

【问题讨论】:

    标签: c gcc macros comments


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      我刚刚阅读了您的 C/C++ Tip #5,发表于 2001 年 1 月号 CUJ。提示的内容(做一个扩展成 评论)非常熟悉,因为我看到部署了类似的方法 在 Microsoft 的一个头文件中。不过小费很 不正确。

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

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

      谢谢,

      本·康比 首席软件架构师 Veriprise 无线 http://www.veriprise.com

      据此,此通知后的期刊:

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

      【讨论】:

      • 谢谢大家的解释。实际上,这个问题来自于我在我的项目上运行夹板并且夹板在类似于 COMMENT 的行上失败的情况。然后我写了 atest.c 并在 gcc 上测试了 COMMENT。然而,令我惊讶的是,当我在上面的 atest.c 上运行夹板时,夹板很高兴并给出消息“atest.c(16,13): Variable attest declared but not used”。
      【解决方案3】:

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

      您可以使用命令 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/
      

      通常诸如 // 之类的 cmets 会被删除并替换为单个“评论标记”,这一步是在预处理之前完成的(当 # 指令发生时),因此即使您可以在其中获得您的评论,我也对此表示怀疑将始终被识别(AFAIK 标准不保证它)。

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

      【讨论】:

        猜你喜欢
        • 2013-03-10
        • 1970-01-01
        • 1970-01-01
        • 2018-03-28
        • 1970-01-01
        • 2011-07-23
        • 1970-01-01
        • 2011-06-06
        • 1970-01-01
        相关资源
        最近更新 更多