具有旧样式函数的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,这使得它成为一个不同的函数。