1

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

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

编辑: 是的,我在 32 位机器上使用 gcc。我很想知道使用其他编译器会得到什么结果。

根据 Christoph 的建议,我对事情进行了一些干预:

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

4

3 回答 3

11

重新排序printf()语句,您会发现它不再起作用,因此 GCC 肯定不会在您背后解决任何问题。

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

关于您修改后的示例:

  • 第一次调用将打印一个双精度值,其中较高的 32 位是垃圾,而指针的位值较低f
  • 第二个调用打印*f提升为双精度的值
  • 第三个调用打印一个双精度值,其中较高的 32 位来自(double)*f(因为这些位仍然保留在上次调用的堆栈中);与第一种情况一样,低位将再次来自指针f
于 2009-11-22T17:41:38.817 回答
1

这些数字对我来说打印不正确。

输出:

123.456001
0.000000

我正在使用 VC++ 2009。

于 2009-11-22T17:30:55.847 回答
1

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

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

在其他平台或其他数据类型上,这可能不起作用。

于 2009-11-22T17:32:54.767 回答