在C中缺少原型声明时,由于参数提升导致了奇怪的结果

时间:2011-09-18 10:48:17

标签: c types prototype

我遇到了一个问题,可归纳如下,

#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

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的结果。