为什么以下程序不会抛出错误:
dfljshfksdhfl;
#include <stdio.h>
int main () {
return 0;
}
gcc
会发出警告:
test.c:1:1:警告:数据定义没有类型或存储类[默认启用]
答案 0 :(得分:7)
这是因为即使implicit int is no longer part of the C standard since C99一些编译器仍然支持它,主要是为了防止破坏很多旧代码。所以这一行:
dfljshfksdhfl;
最终相当于:
int dfljshfksdhfl;
clang
默认为我们提供了更多信息警告:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
dfljshfksdhfl;
^~~~~~~~~~~~~
我们可以使用-pedantic-errors标记将其转换为错误,但奇怪的是,这对clang
不起作用,因此我们不得不诉诸-Werror
并将所有警告转为错误,这实际上是一个很好的习惯。正如remyabel指出clang
我们也可以使用-Werror=implicit-int
。
答案 1 :(得分:1)
我已经回复了similar question(实际上我很确定它是重复的,但无论如何),答案可以在C99理由中找到。
C99的新功能:
在C89中,声明中可以省略所有类型说明符 声明中的说明符。在这种情况下,暗示了int。该 委员会认为这一特征的内在危险性超过了 它的便利性,所以它被删除了。效果是保证 生产一种诊断剂,可以捕获另一类 编程错误。发出诊断后,执行 可以选择假设一个隐含的int并继续翻译 程序,以支持利用此功能的现有源代码 特征强>
@ Shafik的回答告诉你一种方法将警告变为错误(对于Clang)。如果您认为-Werror
过于严格,可以使用-Werror=implicit-int
将该警告变为错误。在海湾合作委员会中,似乎-pedantic-errors
是必要的。
答案 2 :(得分:0)
首先,默认情况下,gcc不是一个符合标准的C编译器。它实现了带有GNU扩展的C89 / C90方言。
您可以使用-std=cNN -pedantic
(NN
可以是90
,99
或11
)使其(尝试)符合指定版本的ISO C标准。 C90允许隐式int
;它在C99中被删除了。
但C编译器实际上并不是必需来生成致命的错误消息(#error
指令除外)。标准的要求(N1570 5.1.1.3p1)是:
符合要求的实施应至少产生一种诊断 消息(以实现定义的方式标识)如果a 预处理翻译单元或翻译单元包含一个 违反任何语法规则或约束,即使行为是 也明确指定为未定义或实现定义。 在其他情况下不需要生成诊断消息。
非致命警告符合&#34;诊断消息&#34;。符合标准的C编译器可以为任何错误打印警告 - 甚至是语法错误 - 然后继续成功编译源文件。 (这是支持某些特定于编译器的语言扩展的方式。)
就个人而言,我发现gcc对某些错误过于宽松;在我看来,缺少int
应该被视为致命错误。但这只是我的偏好,而不是标准规定的要求。
这里的教训是,你不应该认为纯粹的警告是无害的。理想情况下,编译代码应该不会产生任何诊断 。可以忽略警告的情况很少见(但它们确实存在,因为编译器可以自由地警告完全有效的代码)。