【问题标题】:Using \ to extend single-line comments使用 \ 扩展单行注释
【发布时间】:2018-11-24 06:44:05
【问题描述】:

我刚刚注意到我可以使用\ 将单行注释扩展到下一行,类似于在预处理器指令中这样做。

为什么没有人为这个语言功能说话? 我什至没有在书上看到它。。 什么语言版本支持这个?

【问题讨论】:

  • 评论或macro?评论也可以通过* 扩展.. /* 评论 * __________ */
  • @Gopi 评论//
  • 你只需要转义newline,基本上它还是一个单行注释。
  • 我刚刚测试过,它也适用于字符串。我可以在新行中传输字符串,而无需额外的一对 "s,尽管我失去了标识。
  • 每对反斜杠和换行符都被预处理器删除。引用 c11 标准,5.1.1.2 :“每个反斜杠字符 () 的实例紧跟换行符被删除,拼接物理源代码行以形成逻辑源代码行。”

标签: c comments c-preprocessor


【解决方案1】:

它是C的一部分。称为线拼接

K&R 书中谈到了它

以反斜杠字符 \ 结尾的行通过删除反斜杠和 跟随换行符。这发生在划分令牌之前。

这发生在预处理阶段。

所以可以让单行 cmets 看起来像多行一样

//This is \
still a single line comment

字符串的情况也是如此

char str[]="Hello \
world. This is \
a string";

编辑:如 cmets 中所述,单行 cmets 在 ANSI C 中不存在,但在 C99 中作为标准的一部分引入,尽管许多编译器已经支持它。

From C99,

除了在字符常量、字符串文字或注释中,字符 // 引入了一个注释,该注释包括所有多字节字符,但不包括下一个换行符。仅检查此类注释的内容以识别多字节字符并找到终止换行符。

就线拼接而言,在C89本身有规定

2.1.1.2 Translation phases

  1. 换行符和紧接在前面的反斜杠字符的每个实例都被删除,将物理源代码行拼接成逻辑源代码行。非空源文件应以换行符结尾,换行符之前不应紧跟反斜杠字符。

查看 KamiKaze 的答案以查看 C99 的相关部分。

【讨论】:

  • 我相信在编写 K&R 时单行 cmets 不存在,所以我会在有限的范围内采取与这些相关的任何内容
  • C99 标准中增加了单行 cmets。但是在更早的时候就可以在编译器上使用,因为 C++ 有它们。
  • 我仍然认为您的答案是正确的,因为它通常在谈论线条。所以它不关心它是注释、宏还是代码。无论如何都是拼接的。这包括非官方的单线 cmets。所以也许值得指出的是,它一般与 cmets 无关,而是一种语言特性。
  • 确实是正确的。这只是参考通常可能已经过时了。
  • @KamiKaze Eugene 是的。 C99 标准是比 K&R 书更好的参考,因为当时单行注释并不是标准的一部分。
【解决方案2】:

这不是 cmets 的特性,而是该语言的一般特性,因为它适用于所有换行符。

C99 standard找到以下内容:

5.1.1.2 翻译阶段

  1. 后跟换行符的反斜杠字符 () 的每个实例都被删除,将物理源代码行拼接成逻辑源代码行。只有任何物理源行上的最后一个反斜杠才有资格成为此类接头的一部分。非空源文件应以换行符结尾,在任何此类拼接发生之前,该换行符之前不应紧跟反斜杠字符。

所以它至少符合 C99 的标准。 没有太多讨论,因为相关用例(大型宏和字符串除外)非常罕见。如果您需要多行注释(C 中的标准注释,// 是后来从 C++ 中添加的),您可以使用

/* multi
   line
   comment
*/

除了大的宏和字符串之外的每一次使用都会使代码更难阅读,甚至可能会让人很困惑。因此,除了提到的利基之外,一般不使用它。

【讨论】:

    【解决方案3】:

    虽然\ 确实会在单行注释末尾有效地转义换行符,并将该行与下一行拼接起来(就像在任何其他行上一样),但您可以声称这是标准中的一个错误。无论如何,情况非常混乱。您可能认为这两个事实都是正确的:

    1. 单行注释语法// 将行的其余部分(直到下一个换行符)转换为注释,不会以任何方式解释,即被忽略。

      李>
    2. 在任何行的末尾,\ 字符会消除换行符并将该行拼接到下一行。

    但是这两条规则基本上是冲突的;看起来它们不能同时为真。

    现在事实上,根据定义,第二条规则“获胜”,而第一条规则确实必须说,该行的其余部分不会以任何方式解释除了检查最后一个字符是否为@ 987654324@,这样就保留了它的拼接含义

    (现在,如果您是编译器作家或语言律师,当然,您不会那样想。如果您是编译器作家或语言律师,您知道\ 是在编译的早期阶段处理,在解析 cmets 之前,这意味着第一条规则完全正确。但大多数人不像编译器作家和语言律师那样思考。)

    我的意思是,这种情况基本上充满了危险。我敢打赌,那里有编译器或其他语言处理器会出错。我会敦促任何理智的程序员依赖这一点,不要在包含单行注释的任何行的末尾放置\。 (如果我正在编写编译器或其他语言处理器,我会尝试对此发出警告。)

    【讨论】:

      【解决方案4】:

      在解析的第一阶段,在标记化和注释处理之前,每个 \ 实例都会从源中删除,然后是换行符。

      因此,单行注释可以通过使用 \(或 ??/ 三元组序列)转义此换行符来扩展到源代码的下一行:

      // this is a single \
      line comment
      

      请注意 stackoverflow 代码荧光笔是如何被这个技巧愚弄的,并且不会为注释行的末尾着色。

      这个功能可以被进一步滥用来制作看起来很奇怪的 cmets:

      /\
      /\  This is a single line comment /\
      \/                                \/
      
      
      /\
      *\ This is a multi-line comment
      *\
      /
      

      任何令牌都可以通过这种方式破碎。检查这个角落案例:

      \
      r\
      et\
      urn\
       0x7\
      ffff;\
      

      【讨论】:

      • ahaha,我们应该在代码混淆比赛中使用它!这是一些看起来很丑陋的返回声明
      • 不错的退货声明。
      • @Edenia 我打赌他们知道,我打赌他们可以做得更好:D
      • @KamiKaze:或者可以说更糟 ;-)
      猜你喜欢
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      相关资源
      最近更新 更多