使用以下代码:
int main(){
printf("%f\n",multiply(2));
return 0;
}
float multiply(float n){
return n * 2;
}
当我尝试编译时,我收到一个警告:“'%f'需要'double',但参数具有类型'int'”和两个错误:“'multiply'的类型冲突”、“'的先前隐式声明”乘法'就在这里。”
问题1:我猜测这是因为,鉴于编译器第一次遇到函数“乘法”时并不了解它,他会发明一个原型(prototype),并且总是发明原型(prototype)假设'int'既被返回又被作为参数。因此,发明的原型(prototype)将是“int multiply(int)”,因此会出现错误。这是正确的吗?
现在,之前的代码甚至无法编译。但是,如果我将代码分解为两个文件,如下所示:
#file1.c
int main(){
printf("%f\n",multiply(2));
return 0;
}
#file2.c
float multiply(float n){
return n * 2;
}
并执行“gcc file1.c file2.c -o file”,它仍然会给出一个警告(printf 期望 double 但正在获取 int),但错误将不再显示并且它将编译。
问题 2:为什么我将代码分成 2 个文件来编译?
问题 3:一旦我运行上面的程序(版本分为 2 个文件),结果是 0.0000 打印在屏幕上。怎么会?我猜编译器又发明了一个与函数不匹配的原型(prototype),但为什么打印出 0 呢?如果我将 printf("%f") 更改为 printf("%d") 它会打印 1。同样,对幕后发生的事情有任何解释吗?
提前非常感谢。
最佳答案
So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?
绝对是的。这样做是为了向后兼容 ANSI C 之前的版本,因为 ANSI C 缺乏函数原型(prototype),并且没有类型声明的所有内容都是隐式 int
的。编译器编译您的 main
,创建 intmultiply(int)
的隐式定义,但是当它找到真正的定义时,它会发现谎言,并告诉您它。
How come when I break the code into 2 files it compiles?
编译器永远不会发现原型(prototype)的谎言,因为它一次编译一个文件:它假设 multiply
接受一个 int
,并返回一个 int
在您的 main
中,并且在 multiply.c
中没有发现任何矛盾。不过,运行该程序会产生未定义的行为。
Once I run the program above (the version split into 2 files) the result is that 0.0000 is printed on the screen.
这是上述未定义行为的结果。程序将编译并链接,但由于编译器认为 multiply
采用 int
,因此它永远不会将 2
转换为 2.0F
和 multiply
永远不会找到答案。同样,通过在 multiply
函数中将 int
加倍重新解释为 float
计算出的错误值将被视为又是一个int
。
关于c - 有关 C 函数原型(prototype)和编译的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33702652/