【问题标题】:Multiline preprocessor macro with trailing comments带有尾随注释的多行预处理器宏
【发布时间】:2016-06-07 16:11:12
【问题描述】:

我想定义以下看起来很普通的宏:

#define MY_ENUM enum MyEnum{ \
    myVal0, \ //Describes this situation
    myVal2  \ //Describes that situation
}

令我惊讶的是,由于error: stray ‘\’ in program,这不起作用。即使是反斜杠后的一些空格也会导致warning: backslash and newline separated by space。正如this answer 指出的那样,反斜杠必须是该行的最后一个字符。 This answer 指出在处理 cmets 之前会发生线拼接。选择这个顺序的原因对我来说完全没有意义;我能想到的唯一原因是允许多行 cmets 如下所示:

//This is a comment which \
follows in the next line

这看起来非常危险,因为这样的事情可能会在尝试时吃掉下一行的任何代码。相反的顺序,即在拼接线之前用单个空格替换每个注释对我来说听起来是一个更明智的选择。有人能解释一下为什么做出这个选择吗?

我可以通过以下方式解决我原来的问题:

#define MY_ENUM enum MyEnum{ \
    myVal1, /*Describes this situation*/ \
    myVal2  /*Describes that situation*/ \
}

我在做这个尴尬的枚举宏定义时的目的是这个宏必须在 c++(由于 Qt 它绝对必须是类成员)和 c 之间共享。定义这样的宏对我来说似乎是唯一的解决方案,但上述解决方法看起来很难看,我绝对不想让枚举不加注释。我处理这个问题有错吗?

【问题讨论】:

  • 请原谅我的天真,但为什么需要枚举宏?我会将枚举定义放入头文件中并包含头文件。
  • 你已经描述了你遇到的问题,你已经描述了解决方案。使用/*...*/cmets。
  • 听起来你在问是否可以使用非 C 语法编写 C 代码,因为它看起来更好......这有点奇怪。
  • 请注意,即使在拼接之前识别出 cmets,您的代码仍然无法工作: cmets 被替换为空格,因此您的 `` 无论如何都不会是最后一个字符。
  • "...拼接发生在处理 cmets 之前。这个顺序对我来说绝对没有意义;" --> 毕竟它被称为pre-处理器,因为它处理输入评估它的C C++代码。

标签: c++ c gcc g++ c-preprocessor


【解决方案1】:

问题在于,当\ 被击中并继续时,c 预处理器只是添加了另一个行结束字符。

// cmets 内你不能这样做。不接受 \ 字符来继续注释(无论如何它应该显示为单行)。


解决方案是——正如你自己发现的——使用/**/ 评论风格。

【讨论】:

  • 行拼接首先发生,将包括 cmets 在内的整个宏定义放在一条线上......所以第一个 // cmets 将宏定义的其余部分放在一起。使用/* */ cmets,可以在行尾之前关闭注释,这就是该样式仍然有效的原因。
【解决方案2】:

要理解这种现象,你可以参考C标准(我相信C++在这方面与C很相似)。特别是在翻译阶段部分(C11 草案§5.1.1.2)。

预处理器的行为就像以自上而下的顺序执行阶段一样(即在步骤 2 完全完成后执行步骤 3 等)。

基本上,///* ... */ cmets 在第三阶段被识别,即在尾随 \ 处理(即第二阶段)之后执行,这意味着它对它们来说是不可知的.换句话说,它把它们当作普通的源文本,没有特殊含义。

  1. 每个反斜杠字符 (\) 的实例后面紧跟一个换行符都被删除,将物理源代码行拼接到 形成逻辑源代码行。只有任何物理上的最后一个反斜杠 源行应有资格成为此类拼接的一部分。

  2. 源文件分解为预处理标记7) 和空白字符序列(包括 cmets)。源文件不应以部分预处理标记或部分注释结尾。每个注释由一个空格字符替换。保留换行符。是否每个非空的空白序列 除换行符以外的字符被保留或替换为一个空格 字符是实现定义的。

【讨论】:

  • 我修改了问题文本以澄清我已经知道是这种情况(检查我在问题中提供的参考资料),我不明白为什么会做出这个选择。跨度>
猜你喜欢
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 2020-04-06
  • 1970-01-01
  • 2014-01-27
  • 2011-05-14
相关资源
最近更新 更多