我运行了以下代码,发现了一些奇怪的输出。
int
mean_ansi (int num1, int num2)
{
printf ("In %s\n", __FUNCTION__);
printf ("num1,num2 is %d,%d\n", num1, num2);
return (num1 + num2) / 2;
}
int
mean_K_and_R (num1, num2)
int num1, num2;
{
printf ("In %s\n", __FUNCTION__);
printf ("num1,num2 is %d,%d\n", num1, num2);
return (num1 + num2) / 2;
}
int
main ()
{
int i = 6;
double f = 1.0;
printf ("In %s\n", __FUNCTION__);
printf ("[f,i] = [%f,%d]\n", f, i);
/* deliberate mistakes */
mean_ansi (f, i);
mean_K_and_R (f, i);
return 0;
}
输出:
主要
[f,i] = [1.000000,6]
在mean_ansi
num1,num2是1,6
在mean_K_and_R
中num1,num2是0,1072693248
任何人都可以解释这种行为。
我看到了集会,但结果不是很多。
在这两种语法中,函数参数在堆栈上的推送方式是否存在差异?
答案 0 :(得分:4)
Dan Olson有正确的想法,Slartibartfast解释了价值观来自哪里:
mean_K_and_R()
的定义被视为如此定义
int mean_K_and_R();
即该函数接受任何参数,除了默认参数提升之外不进行任何转换。
如果使用cdecl调用约定,这意味着mean_K_and_R(f, i)
将首先将i
推送到堆栈,然后是f
的高位,然后是f
的低位}。
但该函数认为它需要两个整数参数,这意味着num1
现在将f
和num2
的低位引用到f
的高位。< / p>
答案 1 :(得分:2)
我做了一些挖掘并找到了一个thread,表明K&amp; R样式函数声明不会创建原型,因此如果没有单独的原型,编译器可以根据需要自由地处理参数。
我不确定这是多么真实,您可以通过快速插入原型并查看函数是否生成相同的值来验证它。
在任何情况下,K&amp; R风格的声明都非常过时,因为我相信你知道,并且应该避免。如果有什么问题就是一个例子。
答案 2 :(得分:2)
我的猜测是,在第一种情况下,存在double
到int
的隐式转换。在第二个中,表示1.0的64位被解释为两个整数。编号1072693248表示为binnary为
00111111111100000000000000000000
但是如果你看看this page,你会发现这实际上是数字1的双重表示的上半部分。第一个0是符号,01111111111是指数,其余零是上限分数。我唯一没有得到的是1分数去了哪里?说完所有这些后,我希望输出为1,1072693248。