2009-11-22 53 views
1

我知道这是错误和GCC会给你一个警告,但它为什么会工作(即数字打印正确,有一些舍入差异)?怪异的结果打印指针作为浮点数C

int main() { 
    float *f = (float*) malloc(sizeof(float)); 
    *f = 123.456; 
    printf("%f\n", *f); 
    printf("%f\n", f); 
    return 0; 
} 

编辑: 是的,我用gcc有32位机。我很好奇,看看我会用其他编译器得到什么结果。

我插手的东西多一点以下克里斯托夫的建议:

int main() { 
    float *f = (float*) malloc(sizeof(float)); 
    *f = 123.456; 
    printf("%f\n", f); // this 
    printf("%f\n", *f); 
    printf("%f\n", f); // that 
    return 0; 
} 

这导致第一个printf打印从最后的printf不同的值,尽管是相同的。

+0

接近正确的:该参数是按值传递,但推指针堆栈只覆盖(晋升)64位浮点的下半部分值 – Christoph 2009-11-22 17:45:04

+0

你应该发布你得到的实际输出。你是在暗示第二个printf实际上打印'123'或类似的东西? – JustJeff 2009-11-22 17:49:54

回答

11

重新排列printf()声明,你会发现它不再起作用,所以GCC定义不会修复你背后的任何东西。

至于为什么它可以工作:由于可变参数的默认参数提升,您实际上会在第一次调用时传递一个double。由于系统中的指针似乎是32位,所以第二次调用只会覆盖64位浮点值的下半部分。

在问候您的变形例:

  • 第一呼叫将打印一个双精度值,其中较高的32位是垃圾和指针的较低的比特值f
  • 第二呼叫将打印值*f提升为双精度
  • 第三次调用打印一个双精度值,来自(double)*f的较高32位(因为这些位仍然保留在上次调用的堆栈中);在第一种情况下,低位将再次来自指针f
1

这些数字打印不正确。

输出:

123.456001 
0.000000 

我用VC++ 2009

1

printf没有关于实际参数类型的知识。它只是分析格式字符串并相应地解释堆栈中的数据。

巧合(或多或少=))指向float的大小与float(32位)在您的平台上的大小相同,因此在从中删除该参数后,堆栈会保持平衡。

在其他平台上或与其他数据类型可能无法正常工作。