【问题标题】:Single line comment continuation单行注释续
【发布时间】:2015-08-06 22:14:44
【问题描述】:

根据 C++ 标准(至少可以追溯到 C++98)§ 2.2,注 2 状态:

每个反斜杠字符 (\) 的实例后面紧跟一个换行符被删除,拼接物理源代码行以形成逻辑源代码行。只有任何物理源行上的最后一个反斜杠才有资格成为此类接头的一部分。除了在原始字符串文字中恢复的拼接外,如果拼接产生的字符序列与通用字符名称的语法匹配,则行为是未定义的。如果源文件不为空且不以换行符结尾,或者在任何此类拼接发生之前以换行符结尾且紧接反斜杠字符结尾,则应将其视为附加的 new-行字符被附加到文件中。

并且,第 2.7 节规定:

字符 /* 开始一个注释,它以字符 */ 结束。这些 cmets 不筑巢。字符 // 开始一个注释,它以下一个换行符结束。如果此类注释中有换页符或垂直制表符,则它与终止注释的换行符之间只能出现空白字符;不需要诊断。 [注意:注释字符 //、/* 和 */ 在 // 注释中没有特殊含义,它们的处理方式与其他字符一样。同样,注释字符 // 和 /* 在 /* 注释中没有特殊含义。 ]

我将这两者放在一起表示以下意思:

// My comment \
is valid

// My comment \ still valid \
is valid

在 C++98 中是合法的。在 GCC 4.9.2 中,它们都在没有任何诊断消息的情况下编译。在 MSVC 2013 中,这些都产生以下结果:

warning C4010: single-line comment contains line-continuation character

如果您启用了作为错误的警告(我确实这样做了),这会导致程序无法成功编译(没有警告作为错误,它工作得很好)。标准中是否存在不允许单行注释延续的内容,或者这是 MSVC 不符合标准的情况?

【问题讨论】:

    标签: c++ comments


    【解决方案1】:

    我会说 MS 对这样一个事实很敏感:如果您执行以下操作:

    #define macro() \
        some stuff \
        // Intended as comment \
        more stuff
    

    那么当您在代码中使用macro() 时,您会遇到非常有趣的错误。

    或者其他只是不小心输入了这样的评论:

    // The files for foo-project are in c:\projects\foo\
    int blah;
    

    (出现“未定义变量等等”的奇怪错误)

    我绝不会在单行注释中使用续行,但如果您有充分的理由,请在 MSVC 中关闭该警告。

    正如迈克所说:标准甚至没有涵盖警告 - 它只说明需要出现的错误。如果您启用“警告是错误”,您将不得不选择您启用的警告,或者接受一些技术上有效(但可疑)的构造在构建中将是不可接受的,因为编译器制造商已决定警告关于它。尝试在 gcc 或 clang 中编写 if (c = getchar()) ,看看你在多大程度上得到了 -Werror 和“高”警告。然而,按照标准,它是完全有效的。

    【讨论】:

    • 从我对标准的阅读来看,既没有警告或错误(因为 MSVC 和 gcc 使用它们),只有当程序违反任何规则时的“诊断消息”(除非没有特别要求)规则)。在这种情况下,您的实现可以决定是否尝试生成该程序,即使它格式错误或放弃。错误(在实际的编译器术语中)是违反了编译器决定它不想继续执行的规则,警告是它确实继续执行的规则。
    • 我认为标准并没有说明编译器应该如何处理技术上完全错误的事情(例如未声明的变量,将结构分配给 int 变量等) - 在第一个错误处停止,尝试继续,不管你是否真的从中获得了二进制/对象文件/可执行文件。但是警告是标准中最多包含建议的情况,当然不是“代码无效”。警告可以帮助程序员避免愚蠢/常见的错误 - 例如 gcc 坚持在 if ((c = getchar())) ... 中使用额外的括号
    • 请注意,这里的重点是您启用了“错误警告”。这意味着您相信编译器会对标准接受的东西更加严格,但(有时)会导致问题。如果您不希望这样,请不要打开错误警告。或者关闭你认为没有意义的特定警告[使用#pragma,如果你愿意,你可以在一小段代码上做到这一点]
    • 我完全理解这个警告的原因,从实际开发的角度来说,我觉得有它还是不错的。您指出的情况可能会发生,并且警告将有助于诊断它们(主要是第一个 - 第二个可能会导致另一个错误)。我的问题实际上是关于不符合 MSVC 的问题,所有答案/cmets 似乎都证实它不符合标准,具体取决于编译选项 - 但 gcc(以及可能所有其他编译器)也是如此。
    • 我认为编译器只符合“将警告视为错误”关闭的情况[并且可能需要正确设置一些其他选项以确保编译器“遵循标准”]。正如我在 if 语句中使用时在 c = getchar() 周围加上括号的示例所示。根据标准,这显然是正确的代码,但在启用警告时并非“完美无缺”。
    【解决方案2】:

    这不是合规问题。您已明确要求编译器将有效构造视为错误,所以它就是这样做的。

    如果您指定-Wcomment-Wall,GCC 将给出相同的警告(或错误,如果需要)。

    【讨论】:

    • 我没有为 MSVC 提供任何额外的标志来实际生成警告,这只是使用默认选项进行编译(/WX 除外)。我在这里非常挑剔,只是因为我很好奇。虽然我喜欢拥有 -Werror + /WX 的能力,但它似乎会导致不合规,特别是在代码实际上合规的情况下(假设此代码是)。我问了一个后续问题,stackoverflow.com/questions/30438718/…
    • @MuertoExcobito:“如果您启用了错误警告(我愿意)”
    猜你喜欢
    • 2015-07-15
    • 2014-10-21
    • 1970-01-01
    • 2011-10-27
    • 2010-12-03
    • 2012-07-28
    • 2014-09-29
    • 2011-02-08
    • 2016-09-26
    相关资源
    最近更新 更多