【问题标题】:Weird result printing pointers as float in C奇怪的结果将指针打印为 C 中的浮点数
【发布时间】:2009-11-22 17:25:29
【问题描述】:

我知道这是错误,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 不同,尽管它们是相同的。

【问题讨论】:

  • 几乎正确:参数按值传递,但将指针推入堆栈只会覆盖(提升的)64 位浮点值的下半部分
  • 你应该发布你得到的实际输出。您是在暗示第二个 printf 实际上是在打印“123”或类似的东西吗?

标签: c pointers gcc floating-point printf


【解决方案1】:

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

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

关于您修改后的示例:

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

【讨论】:

    【解决方案2】:

    我没有正确打印数字。

    输出:

    123.456001
    0.000000
    

    我正在使用 VC++ 2009。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2011-09-20
        • 1970-01-01
        • 1970-01-01
        • 2013-04-27
        • 2020-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-16
        相关资源
        最近更新 更多