it-swarm.cn

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

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

文件末尾没有换行符

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

177
LeChuck2k

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


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

从C++ 11标准到James'帖子:

一个非空的并且不以换行符结尾的源文件,或者在任何此类拼接发生之前以反斜杠字符开头的新行字符结尾的源文件,应被视为另外一个新文件 - 行字符被附加到文件中(C++11§2.2/ 1)。

206
TJ Seabrooks

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

一个非空的并且不以换行符结尾的源文件,或者在任何此类拼接发生之前以反斜杠字符开头的新行字符结尾的源文件,应被视为另外一个新文件 - 行字符被附加到文件中(C++11§2.2/ 1)。

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

41
James McNellis

C++ 03标准[2.1.1.2]声明:

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

23
Igor Semenov

“顺从”的答案是“因为C++ 03标准说未在新行中结束的程序的行为未定义”(释义)。

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

15
Vytautas Shaltenis

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

大多数文本编辑器会在文件的最后一行末尾添加换行符,因此如果最后一行没有换行符,则存在文件被截断的风险。但是,有充分的理由说明为什么您可能不需要换行符,因此它只是一个警告,而不是错误。

6
Leigh Caldwell

#include将用文件的文字内容替换它的行。如果文件没有以换行符结尾,那么包含拉入它的#include的行将与下一行合并。

5
moonshadow

当然,在实践中,每个编译器都会在#include之后添加一个新行。值得庆幸的。 - @mxcl

不是特定的C/C++而是C语言:当使用GL_ARB_shading_language_include扩展时,OS X上的glsl编译器警告你 _不_ 关于缺少的换行符。所以你可以写一个MyHeader.h文件,其中一个标题保护以#endif // __MY_HEADER_H__结尾,你 - 在#include "MyHeader.h"之后丢失该行肯定。

2
Jan-Philip Loos

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

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

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

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

2
skyking

我正在使用c-free IDE version 5.0,在我的程序中,无论是'c ++'还是'c'语言,我都遇到了同样的问题。只是 在程序结束时 即最后一行程序(在功能的大括号之后它可能是主要的或任何功能), 按enter - 行号。将增加1.然后执行相同的程序,它将运行没有错误。

2
divesh

此警告也可能有助于指示文件可能以某种方式被截断。确实,编译器可能会抛出编译器错误 - 特别是如果它位于函数中间 - 或者可能是链接器错误,但这些可能更加神秘,并且不能保证会发生。

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

0
mwfearnley