关于C函数原型和编制问题 [英] Questions about C Function Prototypes and Compilation
问题描述
通过以下code:
INT的main(){
的printf(%F \\ N,乘(2));
返回0;
}浮动乘法(浮点N){
返回N * 2;
}
当我尝试编译我得到一个警告:'%F'预计'双',但参数的类型'诠释'和两个错误:冲突的类型'乘',previous隐声明'乘'在这里。
问题1 :我猜测这是因为,由于编译器没有的功能乘法,当他遇到它的第一次,他将创造一个原型的知识,并发明原型总是假设'诠释'既是返回,并作为参数。这样的本发明的原型是整数乘法(int)的,并因此错误。这是正确的?
现在,在previous code甚至不会编译。但是,如果我突破code在两个文件中是这样的:
#file1.c中
诠释主(){
的printf(%F \\ N,乘(2));
返回0;
}#file2.c中
浮动乘法(浮点N){
返回N * 2;
}
和执行海湾合作委员会在file1.c file2.c中-o文件,它还是会给予一次警告(即printf的期待双,但越来越INT),但误差不会出现了,它会编译。
问题2 :为什么当我突破code到2个文件它编译
?问3 :当我运行上面的程序(版本分裂成2个文件)的结果是0.0000印在屏幕上。怎么来的?我猜编译器重新发明了一种原型不匹配的功能,但为什么是0打印?如果我改变的printf(%F)对printf(%D),它打印1.再次,这是怎么回事幕后的任何解释?
非常感谢在前进。
于是所发明的原型将是INT乘法(INT),并因此错误。这是正确的?
块引用>当然可以。这对于pre-ANSI C的向后兼容性,缺乏函数原型做,什么都没有宣布一个类型是隐含
INT
。编译器编译你的主
,创建INT乘以(INT)
的一个隐含的定义,但是,当它找到真正的定义,它发现了谎言,并告诉你这件事。
为什么当我突破code到2档它编译?
块引用>编译器从未发现的谎言原型,因为它编译一个文件时:它假定
乘
需要一个INT
,并返回一个INT
的主
,并没有发现任何矛盾multiply.c
。运行这个程序产生不确定的行为,虽然。
在我上面跑(版本分裂成2个文件),该程序的结果是0.0000印在屏幕上。
块引用>这是上述未定义行为的结果。该程序可以编译和链接,但因为编译器认为
乘
需要一个INT
,它永远不会转换2
到2.0F
和乘
永远不会发现。同样的,不正确的值加倍的INT
的 reinter preTED 的一个浮动
里面的乘
功能将被视为一个INT
试。With the following code:
int main(){ printf("%f\n",multiply(2)); return 0; } float multiply(float n){ return n * 2; }
When I try to compile I get one warning: "'%f' expects 'double', but argument has type 'int'" and two errors: "conflicting types for 'multiply'", "previous implicit declaration of 'multiply' was here."
Question 1: I am guessing that it's because, given the compiler has no knowledge of function 'multiply' when he comes across it the first time, he will invent a prototype, and invented prototypes always assume 'int' is both returned and taken as parameter. So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?
Now, the previous code won't even compile. However, if I break the code in two files like this:
#file1.c int main(){ printf("%f\n",multiply(2)); return 0; } #file2.c float multiply(float n){ return n * 2; }
and execute "gcc file1.c file2.c -o file" it will still give one warning (that printf is expecting double but is getting int) but the errors won't show up anymore and it will compile.
Question 2: How come when I break the code into 2 files it compiles?
Question 3: Once I run the program above (the version split into 2 files) the result is that 0.0000 is printed on the screen. How come? I am guessing the compiler again invented a prototype that doesn't match the function, but why is 0 printed? And if I change the printf("%f") to printf("%d") it prints a 1. Again, any explanation of what's going on behind the scenes?
Thanks a lot in advance.
解决方案So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?
Absolutely. This is done for backward compatibility with pre-ANSI C that lacked function prototypes, and everything declared without a type was implicitly
int
. The compiler compiles yourmain
, creates an implicit definition ofint multiply(int)
, but when it finds the real definition, it discovers the lie, and tells you about it.How come when I break the code into 2 files it compiles?
The compiler never discovers the lie about the prototype, because it compiles one file at a time: it assumes that
multiply
takes anint
, and returns anint
in yourmain
, and does not find any contradictions inmultiply.c
. Running this program produces undefined behavior, though.Once I run the program above (the version split into 2 files) the result is that 0.0000 is printed on the screen.
That's the result of undefined behavior described above. The program will compile and link, but because the compiler thinks that
multiply
takes anint
, it would never convert2
to2.0F
, andmultiply
will never find out. Similarly, the incorrect value computed by doubling anint
reinterpreted as afloat
inside yourmultiply
function will be treated as anint
again.这篇关于关于C函数原型和编制问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!