编译以下代码段时,gcc和clang都只发出警告。请注意\
旁边的int
后的空格:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int \
a = 10;
printf("%d\n", a);
}
GCC
main.c:7:6:警告:反斜杠和换行符以空格分隔[已启用 默认情况下]
铛:
main.c:7:7:警告:反斜杠和换行符以空格分隔 int ^
在5.1.1.2的c99标准中,它说:
反斜杠字符()的每个实例紧跟一个 删除换行符,拼接物理源行以形成 逻辑源代码行。
为什么C编译器不符合C标准?我认为只有他们的创作者决定不这样做。我在gcc邮件列表上发现了一条消息,我认为这引发了这种行为:http://gcc.gnu.org/ml/gcc-patches/2000-09/msg00430.html。在那里,他们说这是完成的,因为尾随空格是常见的,他们不想将它们视为错误。这有多常见?
答案 0 :(得分:3)
使用正确的选项进行编译,gcc
和clang
将拒绝进行翻译:
$ gcc -Wall -Werror -std=c11 -pedantic tst.c
tst.c: In function ‘main’:
tst.c:6:9: error: backslash and newline separated by space [-Werror]
cc1: all warnings being treated as errors
$
默认情况下gcc
在启用了GNU扩展的c89模式下编译,非常放纵。
答案 1 :(得分:3)
只要文档gcc
在6.21 Slightly Looser Rules for Escaped Newlines部分的文档中所做的更改,就允许编译器扩展语言。
最近,预处理器放宽了对转义换行的处理。以前,换行必须立即采取反斜杠。当前实现允许空格,水平和垂直制表符形式的空格,以及反斜杠和后续换行符之间的换页符。预处理器发出警告,但将其视为有效的转义换行符,并将这两行组合在一起形成一条逻辑行。这适用于注释和令牌以及令牌之间。出于放松的目的,注释不被视为空白,因为它们尚未被空格替换。
和clang
strives to support gcc
个扩展程序并指向它们上的gcc
文档:
本文档描述了Clang提供的语言扩展。除了此处列出的语言扩展,Clang还旨在支持广泛的GCC扩展。有关这些扩展的更多信息,请参阅GCC手册。
因此他们履行了与标准相关的义务。事实上Linux depends on many gcc extensions。我们可以通过查看草案C99标准部分4.
一致性段 6 来看到这一点,其中说:
脚注3说:[...]符合要求的实施可能有扩展(包括附加 库函数),只要它们不改变任何严格符合的行为 程序。 3)功能
这意味着符合要求的实施不保留本国际标准中明确保留的标识符以外的标识符。
和段 8 :
实现应附有一个文档,该文档定义了所有已定义的实现和特定于语言环境的特征以及所有扩展。
gcc
还记录了您可以使用-pedantic
标记generate a warning when using extensions,并且您可以使用-pedantic-errors
标记来表示错误:
[...]要获得标准所需的所有诊断,您还应指定-pedantic(或-pedantic-errors,如果您希望它们是错误而不是警告)。
答案 2 :(得分:2)
发生这种情况时会生成警告。 不要编写代码 取决于这种行为;提供它是因为尾随 空白很重要(几乎)没有其他地方,我们得到了很多 如果我们将它们视为行继续,则可以更好地恢复错误。 特别是不要编写依赖于能够放置的代码 在一行延续后发表评论,这是一次意外事故 实施并将在未来发生变化。
如果您想要禁用扩展程序,请使用其他答案,启用警告并使用-pedantic-errors
。否则,只要您了解它们提供的含义和好处,就可以随意使用编译器提供的任何功能。如果您想要C99模式,请确保将-std=c99
添加到命令行。
答案 3 :(得分:1)
您引用了标准中的文字,该文字说明当反斜杠后跟换行时会发生什么。
当有反斜杠后跟空格时,该文本没有告诉我们编译器(或C实现通常)必须做什么。
我在C 2011标准中没有看到任何特定的规则。在其适当位置之外的反斜杠根本不符合C的一般语法和语法,因此根据它出现的位置,它会成为某种违规行为。
2011年5.1.1.3说:
海湾合作委员会这样做了;它会产生一条诊断信息。 (警告是一种诊断。)所以它在这方面符合C 2011。如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的情况,符合要求的实现应至少生成一条诊断消息(以实现定义的方式标识),...