奇怪的结果将指针打印为C中的float

时间:2009-11-22 17:25:30

标签: c pointers gcc floating-point printf

我知道这是错误的,gcc会给你一个警告,但为什么它会起作用(即数字打印正确,有一些舍入差异)?

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

修改 是的,我正在使用带有32位机器的gcc。我很想知道其他编译器会得到什么结果。

在克里斯托夫的建议之后,我更多地干涉了一些事情:

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不同,尽管是相同的。

3 个答案:

答案 0 :(得分:11)

printf()语句重新排序,你会发现它不再有效,所以GCC肯定不会修复你背后的任何内容。

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

关于修改后的例子:

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

答案 1 :(得分:1)

我的打印数字不正确。

<强>输出:

123.456001
0.000000

我正在使用VC ++ 2009。

答案 2 :(得分:1)

printf不了解实际参数类型。它只是分析格式字符串并相应地解释堆栈上的数据。

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

在其他平台或其他数据类型上,这可能无效。