我正在测试代码而我不明白它为什么打印“更高的值为0”。 这是主要功能:
int main() {
double a,b,c;
a=576;
b=955;
c=higher(a,b);
printf("The higher value is %g\n", c);
return 0;
}
在另一个.c中我有这个功能:
double higher(double a, double b){
if (a>b)
return a;
return b;
}
注意:如果我在main.c中放置了更高的()它可以正常工作,但是这样它告诉我更高的值是0.如果我在higer()中抛出返回值,这也有效:
return (int)b;
如果返回double的函数与main()或其他函数在同一.c中,会有区别吗?
答案 0 :(得分:4)
使用C99或C11编译器进行编译并阅读警告。您正在使用没有原型的功能。
如果没有原型,前C99会假定默认情况下返回int
的函数。
C99及更高版本,需要原型。
即使没有启用其他警告:
$ cat test.c
int main()
{
int i = f();
return 0;
}
int f(void)
{
return 1;
}
$ gcc -std=c11 test.c
test.c: In function ‘main’:
test.c:13:2: warning: implicit declaration of function ‘f’ [-Wimplicit-function-declaration]
int i = f();
请注意,如果编译-std=c90
,gcc将不会发出警告,但如果启用警告-Wall
则会发出警告。
因此,由于higher()
预计会返回int
,因此该值会通过分配转换为double
(c
的类型不会更改)。< / p>
现在对于有趣的部分:undefined behaviour(UB,记住这句话!),因为调用和实现函数的签名不同。
可能发生的是根据过程调用标准(PCS)和应用程序二进制接口(ABI) - 检查Wikipedia。简而言之:higher
本身会返回double
。这很可能在浮点CPU寄存器中传递给调用者。调用者OTOH期望在整数CPU寄存器中返回值(由于缺少原型)(碰巧碰巧0
)。
所以,因为他们显然没有传达错误,所以你会得到错误的结果。请注意,这有点推测,取决于PCS / ABI。所有要记住的是这是UB,所以任何事情都可能发生,甚至demons flying out of your nose。
为什么要使用原型:
嗯,你已经注意到了,如果你正确调用一个函数,编译器也不知道。更糟糕的是,它不知道使用了哪种参数类型以及返回了哪种结果类型。这特别是一个问题,因为C会自动转换某些类型(你在这里遇到过)。
由于经典的K&amp; R(预标准)C没有原型,所以对于未知函数的所有参数都被假定为int
/ double
用于调用的标量参数。结果默认为int
。 (很久以前,我可能会遗漏一些部分;我开始使用K&amp; R进行编码,搞乱了类型(这里确切地说是你的问题,但是没有干净的解决方案)等等,把它扔到一个角落里并愉快地编程在Modula中-2直到几年后我尝试了ANSI-C)。
如果现在编译代码,你应该至少符合(并编译)C99,更好地使用当前标准(C11)。