为什么GCC不';是否在文件末尾生成任何关于换行符的警告?

为什么GCC不';是否在文件末尾生成任何关于换行符的警告?,c,gcc,clang,newline,C,Gcc,Clang,Newline,从C11 5.1.1.2翻译阶段开始: 第2段: […]不为空的源文件应以新行结尾 字符,其前面不应紧跟反斜杠 在任何这样的拼接发生之前的字符 这意味着每个源文件必须以换行符结尾 例如: #include <stdio.h> int main() { printf("Hello world\n"); return 0; } 这没关系,因为源文件末尾没有换行符 使用gcc prog.c-Wall-Wextra-std=gnu11-pedantic命令,我在gcc上

从C11 5.1.1.2翻译阶段开始:

第2段:

[…]不为空的源文件应以新行结尾 字符,其前面不应紧跟反斜杠 在任何这样的拼接发生之前的字符

这意味着每个源文件必须以换行符结尾

例如:

#include <stdio.h>

int main() 
{
    printf("Hello world\n");
    return 0;
}
这没关系,因为源文件末尾没有换行符

使用gcc prog.c-Wall-Wextra-std=gnu11-pedantic命令,我在gcc上编译了上述程序。GCC不会生成任何警告或错误

那么,为什么GCC不生成任何警告或错误呢

  • “应”的含义由第4节第2点定义:

    如果违反了出现在约束或运行时约束之外的“应”或“不应”要求,则行为未定义

    你引用的文章不在约束部分。因此,如果源文件不以尾随换行符结尾,则程序具有未定义的行为


    未定义的行为不需要诊断。编译器可以自由地做任何事情。GCC开发人员可能已经决定让程序的行为就像在末尾有一个换行符一样,并且不会用警告来打扰用户。

    该标准没有指定存储在磁盘上的物理字节与构成C程序的逻辑字符之间的任何特定关系。例如,如果源字符集仅使用代码0x00-0x7E,则一致性实现可能会说,任何行的第一个字符将设置高位,而前面是任何其他类型的定界符。这样的实现需要表现为每一行后面都有一个换行符,即使源文件中不会出现换行符(我认为实现不需要允许以与包含单个空白字符的行不同的方式表示完全空白的源行)

    如果一个实现指定一个文本文件由许多行组成,这些行由换行符分隔,并且一个N行文件将包含N-1个换行符,那么它的行为就必须像文件中最后一个字节后面有一个换行符一样。但是,如果实现指定所有有效的文本文件都以作为一个换行符,如果给它一个无效的文本文件,它将不承担任何义务


    请注意,除其他事项外,在某些实现中,
    #include
    后面的第一行可能会连接到包含文件末尾的不完整行。这种行为虽然古怪,但在某些情况下可能有用,并且可能有一些代码依赖于它。考虑到这种拼接,如果预期,可能会产生本质上无限的后果,将行为保留为未定义比尝试对可能发生的事情进行分类更简单。

    有一个问题,换行符没有很好的标准定义,因为不同的系统有不同的换行符约定。但是你是对的……如果标准规定编译器必须在如果合同通用条款没有,则应作为不合规问题提交

    但我同意@supercat的回答,在某种意义上,可以假设没有最终
    \n
    的文件可以安全地解释为一个正确分隔的文本文件,在末尾没有行尾…因为
    \n
    可以解释为一个行分隔符,而不是行尾字符。如果这种解释是valid,空文件将被解析为一个空行文件,编译器在解析它时没有问题,并且在这种情况下不应发出警告。这同样适用于没有最终
    \n
    的任何文件,并且用
    \n
    完成的文件应被解释为
    n+1
    行文件,带有额外的空行(恐怕这对里面C代码的含义没有任何影响)

    如果你去gcc项目投诉的话,你可能会得到这样的回应,所以要谨慎,但不要犹豫,去做吧


    顺便问一下,您是否尝试向编译器提供最后一个
    \\
    字符(没有
    \n
    字符)编译器可以插入最后一个换行符来模拟正确定义的文件,但是预处理器必须以特殊形式处理
    \\
    字符后跟新行的情况。在这种情况下,编译器应该发出一些信息,因为您不能继续超过文件的最后一行。如果e最后一行终止于
    \\
    (这是一个不符合项)让我们看看gcc是什么…(对不起,我现在还没有访问gcc)

    这个问题不是更好地针对gcc项目吗?(不是否决,只是问…)显然,这是一个关于非常重要警告的重要问题!请注意,标准并没有说编译器在这种情况下必须发出警告。我还没有去标准看看它是如何发出警告的……这里唯一要说的是,C标准谈论的是源代码,而不是源代码如何存储在系统上,或者它必须为或要正确解析的文件。假设一个EBCDIC系统具有固定(Hollerith)长度行,没有结束行字符。如何在其上运行C编译器?人们倾向于将自己的环境转换为标准,而不阅读它的第一段,这通常会像我现在说的那样。假设一个系统知道文本文件,并将其存储为表示长度行和否的二进制数换行符。编译器(或其他工具)将需要转换文件格式,以便源代码可以显示并正确地输入编译器。哦,我也完全同意这一推理。我感觉你的第一个错误
    prog.c:7:16: warning: no newline at end of file [-Wnewline-eof]
    }
                   ^