“文件末尾没有换行符”编译器警告

"No newline at end of file" compiler warning

提问人: 提问时间:9/16/2008 最后编辑:Brian Tompsett - 汤莱恩 更新时间:9/4/2022 访问量:122441

问:

在某些 C++ 编译器中出现以下警告的原因是什么?

文件末尾没有换行符

为什么在源文件/头文件的末尾应该有一个空行?

C++ 编译器构造 警告 C-预处理器

评论

18赞 ThiefMaster 11/21/2011
不是真正的原因,但如果你是一个文件并且它没有尾随换行符,那就很烦人了,因为新的 shell 提示符会出现在文件的最后一行之后(即不在第 0 列中)cat
0赞 bames53 2/19/2014
@ThiefMaster 正是出于这个原因,我的 $PS 1 以换行符开头。(无论如何,这是一个多行提示,在一行上包含一堆有用的信息,然后在下一行上只包含一个提示字符,这样相当长的命令就不会换行)
8赞 Brandin 6/22/2014
Why should I have an empty line at the end of a source/header file- 如果一个文本文件包含,则它包含三行,其中没有一行是空的。如果一个文本文件包含,那么它就不是一个文本文件,就像末尾没有句号的句子不是一个句子一样。one\ntwo\nthree\none\ntwo\nthree

答:

6赞 Leigh Caldwell 9/16/2008 #1

它不是指空行,而是最后一行(其中可以包含内容)是否以换行符结尾。

大多数文本编辑器会在文件最后一行的末尾放置换行符,因此,如果最后一行没有换行符,则文件存在被截断的风险。但是,您可能不想要换行符是有正当理由的,因此它只是警告,而不是错误。

16赞 Vytautas Šaltenis 9/16/2008 #2

“服从”的答案是“因为 C++03 标准说不以换行符结尾的程序的行为是未定义的”(释义)。

好奇的答案就在这里:http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html

评论

6赞 shylent 1/17/2010
啊,心爱的“未定义行为”。当其他语言失败时,c/c++ 会以“未定义”的方式运行:)当然,这是他们魅力的重要组成部分。我不是在开玩笑。
6赞 moonshadow 9/16/2008 #3

#include将用文件的文字内容替换其行。如果文件不以换行符结尾,则包含拉入该文件的行将与下一行合并。#include

229赞 TJ Seabrooks 9/16/2008 #4

想想如果没有换行符可能会出现的一些问题。根据 ANSI 标准,文件开头的插入与文件前面完全相同,并且不会在文件内容之后插入新行。因此,如果在解析器末尾包含一个没有换行符的文件,则将被视为 的最后一行与 的第一行在同一行上。如果 foo.h 的最后一行是没有新行的注释怎么办?现在第一行被注释掉了。这些只是可能蔓延的问题类型的几个例子。#include#include <foo.h>foo.hfoo.cppfoo.cpp


只是想在下面指出任何感兴趣的人詹姆斯的答案。虽然上述答案对于 C 仍然是正确的,但新的 C++ 标准 (C++11) 已更改,因此如果使用 C++ 和符合 C++11 的编译器,则不应再发出此警告。

来自 C++11 标准,来自 James 的帖子:

对于不为空且不以换行符结尾的源文件,或者在发生任何此类拼接之前以换行符结尾且紧跟反斜杠字符的源文件,应像在文件中附加了其他换行符一样进行处理 (C++11 §2.2/1)。

评论

31赞 mxcl 10/21/2008
当然,在实践中,每个编译器都会在 #include 后添加一个新行。谢天谢地。
3赞 Greg Hewgill 11/12/2008
我记得旧版本的 Microsoft Visual C++(如 2.x 或其他东西)正好有这个问题。由于 IDE 编辑器鼓励这种缺少换行符的行为,因此情况更加严重。
2赞 Kactung 4/21/2013
编译器目前可能不会抱怨,但 GitHub 确实有。
1赞 mbx 2/11/2014
我可以看到詹姆斯的“下面”答案,但是:“上面的答案”在顺序中是什么?!以上是问题,因为我通常按票数排序。或者你是说你自己的答案?
0赞 Destructor 7/31/2015
@Thomas:此程序是否调用未定义的行为,因为它不以换行符结尾。在此处查看程序: ideone.com/jswwf9
29赞 Igor Semenov 9/16/2008 #5

C++ 标准 [2.1.1.2] 声明:

...如果不为空的源文件不以换行符结尾,或以换行符结尾 在发生任何此类拼接之前,紧跟反斜杠字符,则行为未定义。

50赞 James McNellis 11/18/2011 #6

在 C++11 中,删除了每个源文件都以非转义换行符结尾的要求。该规范现在的内容如下:

对于不为空且不以换行符结尾的源文件,或者在发生任何此类拼接之前以换行符结尾且紧跟反斜杠字符的源文件,应像在文件中附加了其他换行符一样进行处理 (C++11 §2.2/1)。

符合要求的编译器不应再发出此警告(至少在 C++11 模式下编译时,如果编译器具有不同语言规范修订版的模式,则不会发出此警告)。

评论

4赞 Adam Rosenfield 11/18/2011
这对 C++ 来说很好;不幸的是,即使在即将到来的 C1X 标准的最新草案中,C 仍然说它是 UB。
12赞 James McNellis 11/18/2011
这个问题被标记为 [c++] 而不是 [c]。
4赞 Adam Rosenfield 11/18/2011
即便如此,它可能应该被标记为 [c],因为许多在 C 中搜索此警告的人会在这里找到自己的方式。
1赞 TJ Seabrooks 11/21/2011
这仍然是一个值得补充的好点。在上面加起来。希望你不介意。
0赞 mwfearnley 1/8/2012 #7

此警告还可能有助于指示文件可能以某种方式被截断。诚然,编译器可能会抛出编译器错误(尤其是当它位于函数中间时)或链接器错误,但这些错误可能更隐晦,并且不能保证会发生。

当然,如果文件在换行符后立即被截断,也不能保证此警告,但它仍然可以捕获其他错误可能遗漏的一些情况,并为问题提供更强的提示。

2赞 divesh 12/11/2012 #8

我正在使用 c-free IDE 5.0 版,在我的“c++”或“c”语言中,我遇到了同样的问题。就在程序的末尾,即程序的最后一行(在功能大括号之后,它可能是 main 或任何功能),按 enter-line no。将增加 1.然后执行相同的程序,它将运行而不会出错。

3赞 Jan-Philip Loos 12/24/2014 #9

当然,在实践中,每个编译器都会在 #include 后添加一个新行。谢天谢地。– @mxcl

不是特定的 C/C++,而是一种 C 方言:使用扩展时,OS X 上的 glsl 编译器不会警告您缺少换行符。因此,您可以编写一个带有标头保护的文件,该文件以结尾,并且肯定会丢失后面的行。GL_ARB_shading_language_includeMyHeader.h#endif // __MY_HEADER_H__#include "MyHeader.h"

2赞 skyking 8/6/2015 #10

因为如果文件不以换行符结尾,则行为在 C/C++ 版本之间有所不同。特别讨厌的是较旧的 C++ 版本,C++ 03 中的 fx 标准说(翻译阶段):

如果不为空的源文件不以换行符结尾 字符,或以换行符结尾,紧跟 反斜杠字符,则行为未定义。

未定义的行为是不好的:符合标准的编译器可以或多或少地做它想做的事(插入恶意代码或其他什么)——这显然是警告的原因。

虽然 C++11 中的情况更好,但最好避免在早期版本中未定义行为的情况。C++ 规范比 C99 更糟糕,后者完全禁止此类文件(然后定义行为)。

评论

0赞 supercat 8/19/2015
我怀疑标准说没有尾随换行符的程序具有未定义的行为,而不是说明它们的格式不正确,因为一些编译器会将包含文件的未终止的最后一行与指令后面的源代码文本连接起来,并且一些针对此类编译器的程序员可能已经利用了这种行为。让标准将此类内容保留为“未定义”将允许利用此类怪癖的程序在指定此类行为的平台上得到明确定义。让标准强制要求一种行为会破坏此类程序。#include
0赞 Yasin Bekar 9/4/2022 #11

就我而言,我使用 KOTLIN 语言,编译器在 IntelliJ 上。此外,我正在使用带有 LINT 的 docker 容器来修复拼写错误、导入、代码使用等可能的问题。这个错误很可能来自这些 lint 修复 - 我的意思是肯定。

简而言之,错误说,“在文件末尾添加一个新行”就是这样。

Added Line on the file at the END

之前没有多余的空行:

Without new line on the file