C++ 标准(源文件的换行符结尾)

Posted

技术标签:

【中文标题】C++ 标准(源文件的换行符结尾)【英文标题】:C++ Standards (newline ending of source files) 【发布时间】:2015-10-13 00:27:57 【问题描述】:

我指的是:Why should text files end with a newline? 其中一个答案引用了 C89 标准。简而言之,文件必须以新行结尾,而不是紧跟反斜杠。

这是否适用于最新的 C++ 标准?

#include <iostream>
using namespace std;

int main()

  cout << "Hello World!" << endl;
  return 0;

//\

以上内容有效吗? (假设//\后面有一个换行符,我一直无法显示)

【问题讨论】:

“为了保持一致性,遵循这条规则非常有帮助”。 Historically,主要问题是未能在带有#endif 标头保护的 .h 文件后添加换行符。 为什么不自己测试一下? @Jashaszun 嗯,如果我碰巧有一个允许文件以换行符结尾的编译器怎么办?尝试编译并不能证明任何事情。 @Jashaszun:标准的一般经验法则是“对你接受的东西松懈。严格遵守你产生的东西”。因此,在没有歧义的情况下接受不合规输入的编译器不会做“坏工作”。尽管理想情况下它应该警告它接受的任何非标准内容。 @Jashaszun 嗯。 . .这应该是一个弱假设。在大多数情况下,我可以假设如果有错误,是我造成的,而不是编译器。但是,我认为没有一个编译器能够 100% 遵守该标准。 【参考方案1】:

给定的代码在 C++ 的情况下是合法的,但对于 C 是不合法的。

确实,C (N1570) 标准说:

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

C++ 标准 (N3797) 对它的表述略有不同(强调我的):

每个反斜杠字符 (\) 的实例后面紧跟一个换行符都会被删除, 拼接物理源线形成逻辑源线。只有任何物理上的最后一个反斜杠 源线应有资格成为此类接头的一部分。如果,结果,一个字符序列 生成匹配通用字符名称的语法,行为未定义。 源文件 不为空且不以换行符结尾或以换行符结尾的 在任何此类拼接发生之前紧接反斜杠字符之前,应进行处理 好像在文件中附加了一个额外的换行符。

【讨论】:

TL;DR - 在 C 中,每个源文件必须以换行符结尾。在 C++ 中,即使程序员没有提供,编译器也会想象最后的换行符。【参考方案2】:

根据 [lex.phases] p2 和 p3,您的特殊情况在 c++ 标准中也是不正确的。 [lex.phases] p2 说

每个反斜杠字符 () 序列紧跟零个或多个空格字符,而不是换行符后跟一个换行符被删除,拼接物理源代码行以形成逻辑源代码行。只有任何物理源行上的最后一个反斜杠才有资格成为此类接头的一部分。除了在原始字符串文字中恢复的拼接外,如果拼接产生的字符序列与通用字符名称的语法匹配,则行为未定义。非空且不以换行符结尾或以拼接结尾的源文件应被处理,就好像在文件中附加了一个额外的换行符一样。

既然你说

假设在 // 之后有一个换行符,我一直无法显示

因此,最后一个可见的\ 可以作为接头。因此,序列由\ 组成,换行符被删除。这意味着此源文件中的最后一个字符是/,但后面没有换行符。 // 根据 [lex.comment] p1 开始评论

字符//开始注释,在下一个换行符之前终止

根据 [lex.phases] p3

源文件被分解为预处理标记([lex.pptoken])和空白字符序列(包括 cmets)。 源文件不得以部分预处理标记或部分注释结尾

在您的情况下,字符 // 开始注释,但没有新行来终止它。因此,这是一个部分评论。程序格式不正确。

【讨论】:

以上是关于C++ 标准(源文件的换行符结尾)的主要内容,如果未能解决你的问题,请参考以下文章

EOF

C++怎么用eof判断txt文件到文件结尾了没

如何摆脱 Checkstyle 消息“文件不以换行符结尾。”

日常踩坑 解决软件包 xxxx 的文件名列表文件缺少最后结尾的换行符

为啥我的 Linux 文本文件(使用 echo 创建)以换行符结尾?我怎样才能删除它? [复制]

php TRIM()文件内容(删除文件开头和结尾的所有BLANK字符:空格,制表符和换行符,只保留一行换行符