我遇到了一个问题,可归纳如下,
#include <stdio.h>
int main()
{
float f=23.45;
printf("main: %f\n", f);
t1(f);
/* the result would be
main:23.450001
t1:2.000000 */
}
void t1(float f)
{
printf("t1: %f\n", f);
}
我现在知道奇怪的行为是由于缺少原型声明而且因此提升了参数,(float-&gt; double?),我仍然无法弄清楚为什么结果是2.000000,所以任何人都可以提供更多详细解释?我使用的是ubuntu10.04 gcc4.4.3
答案 0 :(得分:6)
您正在观察的行为特定于基于堆栈的参数传递。对于默认编译64位x86代码且无法重现的人,可以尝试使用“gcc -m32”而不是“gcc”。
通过基于堆栈的参数传递,t1()
从堆栈中读取32位,这些32位恰好形成浮点值2.0
。
在调用站点,由于t1
没有原型,因此参数f
被提升为double
并且它是写在堆栈上的double
(C99 6.5) .2.2:6“如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将类型为float的参数提升为double。这些被称为默认参数提升“)。
t1
没有理由从堆栈中恢复预期的值,因为它没有正确读取它的类型和宽度。
答案 1 :(得分:1)
因为编译器不知道t1
采用浮点数,所以它将浮点数提升为double。在您的平台上,t1
将该double的前四个字节解释为float。
2.0表示为1 x 2 ^ 0,二进制为三个零字节,后跟64(在x86-64上)。碰巧的是,23.45作为double有相同的前四个字节,0,0,0,64(后面是51,115,55,64)。因此,如果你取两倍23.45并将它的前四个字节解释为浮点数,你得到2.0。
答案 2 :(得分:0)
请记住,缺少原型意味着稍后将使用int参数声明该函数,并进行适当的转换。所以,我假设如果你在t1的声明中用int替换float,你将得到23的结果。