具有旧样式函数的C编译器的行为,没有原型
当我的程序包含两个文件时:
main.c中
#include int main(void) { printf("%lf\n",f()); return 0; }
func.c
double f(int a) { return 1; }
编译器不显示任何错误。
当我的程序只包含一个文件时:
main.c中
#include int main(void) { printf("%lf\n",f()); return 0; } double f(int a) { return 1; }
Visual C ++ 2008编译器显示以下错误:
Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1
任何人都能解释这种奇怪的行为吗?
这两个程序都错了。
如果没有范围内的原型,编译器会假定函数返回int
并获取未指定数量的参数。
让我们稍微改变你的文件:
$ cat func.c double f(int a) { return 1.0; } $ cat main.c #include int main(void) { double d = f(); printf("%lf\n", d); return 0; }
当我编译它时,gcc警告我(Visual C ++也应该在符合模式下)。 但是让我们忽略这个警告。
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test func.c:1: warning: unused parameter 'a' main.c: In function 'main': main.c:4: warning: implicit declaration of function 'f' $ ./test 0.000000
它没有打印1,而是打印0.这是因为编译器假设f()
返回一个int
,并且赋值d = f();
将“ int
”转换为double
。 编译器仍然编译代码,因为它无法判断f()
是否以(隐式)声明的方式定义。 但是标准不需要编译上面的程序,所以编译器可能会拒绝它(例如尝试使用gcc -Werror
!)
如果我们在一个文件中有所有内容:
$ cat func.c >>main.c $ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test main.c:4: warning: implicit declaration of function 'f' main.c: At top level: main.c:9: error: conflicting types for 'f' main.c:4: error: previous implicit declaration of 'f' was here main.c:9: warning: unused parameter 'a'
现在,编译器会看到冲突,并为您提供错误消息。 但是,编译器不需要拒绝上述程序,它可能会也可能不会。
大多数编译器不拒绝第一个程序,因为他们不知道你是否在另一个翻译单元中对函数f()
有正确的定义。 他们拒绝第二个程序,因为他们知道你没有。
C将假设一个函数具有原型int func(); 除非你另有说明。(注意在C int func();和int func(void);是不同的东西)
在第二种情况下,你调用f()
编译器没有看到任何原型,所以它假设它是int f();
。 稍后它会看到你对f()
定义有不同的原型 – 并发出错误。
这种情况不会发生在1.情况下,因为它们位于不同的编译单元中。
你的第一个例子从不使用func.c
所以我不确定编译器对f()
确切作用,因为它没有定义。
在第二个例子中,我不知道为什么你不能拥有两个具有不同签名的函数,但是你没有调用你定义的函数。 你调用没有参数的f()
,但是你定义的f
采用一个int,这使得它成为一个不同的函数。