“文件末尾没有换行符”编译器警告
Posted
技术标签:
【中文标题】“文件末尾没有换行符”编译器警告【英文标题】:"No newline at end of file" compiler warning 【发布时间】:2010-09-09 11:49:50 【问题描述】:在某些 C++ 编译器中出现以下警告的原因是什么?
文件末尾没有换行符
为什么我应该在源文件/头文件的末尾有一个空行?
【问题讨论】:
不是真的原因,但是如果你cat
一个文件并且它没有尾随换行符,因为新的shell提示符将出现在文件的最后一行之后(即不在第 0 列)
@ThiefMaster 正是出于这个原因,我的 $PS1 以换行符开头。 (无论如何,它是一个多行提示符,在一行中包含一堆有用的信息,然后在下一行只包含一个提示字符,因此相当长的命令不会换行)
Why should I have an empty line at the end of a source/header file
- 如果一个文本文件包含 one\ntwo\nthree\n
那么它包含三行,其中没有一个是空的。如果一个文本文件包含one\ntwo\nthree
,那么它就不是一个文本文件,就像在结尾没有句号的句子不是一个句子一样。
【参考方案1】:
想想如果没有换行符可能会出现的一些问题。根据 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)。
【讨论】:
当然,实际上每个编译器都会在#include 之后添加一个新行。谢天谢地。 我记得旧版本的 Microsoft Visual C++(如 2.x 或其他版本)正是有这个问题。由于 IDE 编辑器鼓励这种缺少换行符的行为,这种情况更加严重。 编译器目前可能不会抱怨,但 GitHub 确实会抱怨。 我可以看到"below" answer by James 但是:OrderBy 中的“上述答案”是什么?!以上是问题,因为我通常通过投票来订购。还是您的意思是您自己的答案? @Thomas:这个程序是否调用了未定义的行为,因为它没有以换行符结尾。在此处查看程序:ideone.com/jswwf9【参考方案2】:在 C++11 中删除了每个源文件都以非转义换行符结尾的要求。规范现在如下:
如果源文件不为空且不以换行符结尾,或者在任何此类拼接发生之前以换行符结尾且紧接反斜杠字符结尾,则应将其视为文件中附加了额外的换行符 (C++11 §2.2/1)。
符合标准的编译器不应再发出此警告(至少在 C++11 模式下编译时不会发出此警告,如果编译器具有针对不同版本的语言规范的模式)。
【讨论】:
这对 C++ 来说很好;不幸的是,即使在即将到来的 C1X 标准的最新草案中,C 仍然说它是 UB。 这个问题被标记为 [c++] 而不是 [c]。 即便如此,它可能应该标记为 [c],因为许多在 C 中搜索此警告的人会在这里找到自己的方式。 这仍然是一个很好的补充。在上面加上这个。希望你不要介意。【参考方案3】:C++03 标准 [2.1.1.2] 声明:
... 如果非空源文件不以换行符结尾,或以换行符结尾 在任何此类拼接发生之前紧跟反斜杠字符,行为未定义。
【讨论】:
【参考方案4】:“听话”的答案是“因为 C++03 标准规定程序的行为不以换行符结尾是未定义的”(意译)。
好奇的答案在这里:http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html。
【讨论】:
啊,心爱的“未定义行为”。当其他语言失败时,c/c++ 会以“未定义”的方式表现 :) 这当然是它们魅力的重要组成部分。我不是在开玩笑。【参考方案5】:这不是指空行,而是最后一行(可以包含内容)是否以换行符终止。
大多数文本编辑器会在文件的最后一行末尾添加换行符,因此如果最后一行没有换行符,则文件可能会被截断。但是,您可能不想要换行符是有正当理由的,因此它只是一个警告,而不是错误。
【讨论】:
【参考方案6】:#include
将用文件的文字内容替换它的行。如果文件不以换行符结尾,则包含将其拉入的#include
的行将与下一行合并。
【讨论】:
【参考方案7】:当然,实际上每个编译器都会在#include 之后添加一个新行。谢天谢地。 – @mxcl
不是特定的 C/C++ 而是 C 方言:当使用 GL_ARB_shading_language_include
扩展时,OS X 上的 glsl 编译器会警告您 NOT 缺少换行符。因此,您可以编写带有以#endif // __MY_HEADER_H__
结尾的标头保护的MyHeader.h
文件,并且您肯定会丢失#include "MyHeader.h"
之后的行。
【讨论】:
【参考方案8】:我正在使用无 c 的 IDE 版本 5.0,在我的“c++”或“c”语言的程序中,我遇到了同样的问题。只是在程序的末尾,即最后一行程序(函数大括号后可能是主函数或任何函数),按回车-行号。加1,再执行同样的程序,就可以正常运行了。
【讨论】:
【参考方案9】:因为如果文件不以换行符结尾,则 C/C++ 版本之间的行为会有所不同。尤其令人讨厌的是较旧的 C++ 版本,标准规定的 C++ 03 中的 fx(翻译阶段):
如果非空源文件不以换行符结尾 字符,或以换行符结尾,前面紧跟一个 反斜杠字符,行为未定义。
未定义的行为是不好的:符合标准的编译器可以在这里或多或少地做它想做的事情(插入恶意代码或其他) - 显然是警告的原因。
虽然 C++11 中的情况更好,但最好避免在早期版本中未定义行为的情况。 C++03 规范比 C99 更糟糕,后者完全禁止此类文件(然后定义行为)。
【讨论】:
我怀疑标准说没有尾随换行符的程序具有未定义行为,而不是说明它们格式错误,因为某些编译器会连接包含文件的未终止的最后一行#include
指令后面的源代码文本,并且一些针对此类编译器的程序员可能已经利用了这种行为。让标准将此类事物保留为未定义将允许利用此类怪癖的程序在指定此类行为的平台上得到良好定义。让标准强制要求某种行为会破坏此类程序。【参考方案10】:
此警告还可能有助于表明文件可能已被截断。确实,无论如何编译器都可能会抛出编译器错误——尤其是在函数中间时——或者可能是链接器错误,但这些可能更神秘,并且不能保证会发生。
当然,如果文件在换行符后立即被截断,也不能保证此警告,但它仍然可以捕获其他错误可能遗漏的某些情况,并为问题提供更强有力的提示。
【讨论】:
【参考方案11】:这不是错误。这只是一个警告。
在编辑器中打开文件,转到文件的最后一行,然后按回车键在文件末尾添加一个空行。
不过,除此之外,您应该使用#include <iostream>
而不是<iostream.h>
。然后在它后面加上一个using std::cout;
。
【讨论】:
以上是关于“文件末尾没有换行符”编译器警告的主要内容,如果未能解决你的问题,请参考以下文章
错误:文件末尾没有换行符 [-Werror,-Wnewline-eof]#endif 在我的 IOS 游戏上进行适当加载时