我目前正在使用GCC 4.4.3.令我感到困惑的是为什么GCC对我(在示例中故意)不匹配(可选)bar的声明及其在bar.c中的定义如此宽容,这显然会导致致命的地址错误 – 因为bar需要一个地址并且给出一个整数,它最终取消引用该整数作为地址.一个严格的编译器,或者我认为,会因为错误而中止我.我错过了什么吗?我的构建命令行如下:
cc -o foobar -g -Wall -std=c99 -fexec-charset=ISO-8859-1 -DDEBUG foo.c bar.c
用foo.c:
int main() { int a; bar(a); return 0; }
和bar.c:
void bar(int * a) { *a = 1; }
我故意省略了bar的声明,并故意传递一个整数(可能是真的)而不是一个地址,因为它的实际定义需要.我的底线是:因为$(CC)不会阻止我,我最终会出现分段错误(x86,Ubuntu 10.04).我知道一个兼容的C(C99?)编译器会隐藏地为bar创建一个int bar(void)声明,如果没有找到,但在这种情况下,这显然不是我想要的!我想保护自己免受各种错误的影响,因为我犯了人为错误的声明和定义不匹配或完全省略了前者.
我尝试使用-c编译器开关代替仅编译 – 但它并不重要,因为它仍然成功发出警告.虽然链接器可能会禁止,但我希望编译器在发生这种情况之前阻止我.
我实际上并不想把我的警告变成错误 – 例如-Werror,因为:
>我可以包括错误的浮动条(双a);在foo.c的顶部,它完全消除了警告,但没有改变生成的程序崩溃的事实.唉,一个在没有警告的情况下成功编译的程序(即使使用-Wall开关)并且在运行时崩溃也很漂亮.
>我已经并将有其他类型的警告,应该保持警告,而不是阻止成功的构建.
>它将处理问题的影响,而不是问题本身
>这不仅仅是警告的类型,还有特定的实例.我不想将特定的警告代码变成错误,因为在某些情况下,这不适用.唉,这将是一个过于粗略的解决方案,没有考虑警告发生的具体情况和背景.
解决方法
试图回答你的“为什么”问题:是的,这可能看起来很奇怪,默认情况下这是一个警告而不是错误.这是出于历史原因.有关细节,请参阅例如Why does/did C allow implicit function and typeless variable declarations?,或者在http://cm.bell-labs.com/who/dmr/chist.html用Ritchie自己的话来读.