【问题标题】:How does printf work? Why is the output different? [duplicate]printf 是如何工作的?为什么输出不一样? [复制]
【发布时间】:2016-06-15 09:03:33
【问题描述】:

考虑这两个程序:

#include <stdio.h>

int main()
{
  int z = 6.4;
  printf("%d %d", z, 6.4);
  return 0;
}

输出是6 -1717986918

#include <stdio.h>

int main()
{
  int z = 6.4;
  printf("%d %d", 6.4, z);
  return 0;
}

输出是-1717986918 1075419545

为什么输出会这样变化?当z 是第一个时,输出打印出正确的z 值,它是6,因为z 是一个整数,但是当我反转参数时,输出是一个不同的值。为什么会这样?

【问题讨论】:

  • 我认为这是 C,但如果我将它编译为 C++,我会得到相同的结果:语言标签可能会让更多人关注
  • 我只收到编译器警告,说 printf 需要一个整数,而我给它一个双精度。但它编译并打印两个六。你用的是什么编译器?
  • @JanezKuhar 代码块
  • 使用 gcc 版本 4.8.4 我得到 4 个六分。但是对于 gcc 5.3.1 版,我得到:第一个 main() 为 6 -1717986918,第二个为 6 6。
  • @JanezKuhar:这并不神秘,它是未定义的行为。具有未定义行为的程序在多次调用时可能在不同系统上产生不同的输出,甚至在同一系统上产生不同的输出。试图解释观察到的特定实例的行为几乎没有用。从法医证据调查某些情况时,可以提出有用的解释和改进方向。想想飞机失事、计算机病毒分析、电子邮件黑客......

标签: c floating-point printf type-punning


【解决方案1】:

您将6.4 存储在一个整数中,这将导致z 成为6。 6 被传递给printf,它传递的值解释为十进制,因此显示了正确的输出。

但是,如果您将浮点数直接传递给printf,并指定格式%d,它也会将其解释为十进制,这将导致该浮点数的十进制解释。

这种解释发生在位级别上。浮点数在内部以相当复杂的格式存储。但不像整数。 现在这些位被解释为整数,显然结果对于人类来说是不可读的。但程序实际上可以将该整数解释为浮点数并反转此操作。

This 站点将演示浮点数如何存储在位级别。

this 网站上,您可以将上一个网站的位转换为有符号整数,该整数应输出您在问题中指定的负数。

【讨论】:

  • 但是在第二个程序中 %d 用于 z 仍然没有输出 6。
  • 发生这种情况是因为 printf 在内部使用了可变参数,并且由于某种原因,数据由于读取错误而损坏。请再次尝试此行,但使用 6.4f 作为参数。我怀疑这是因为编译器将 6.4 作为双精度传递,因此第二个 %d 正在读取该双精度的后半部分。但我可能错了。
  • 传递错误的类型会导致未定义的行为,句号。 printf 甚至可能无法从传递的数据中获取值,并且后面的参数也会出现在错误的位置。试图详细说明实际行为是一个有争议的问题。
  • @SimonKirsten: float 值在传递给可变参数函数时被隐式提升为 double,您的建议没有区别,这并不意味着输出将相同,因为代码未定义行为,每个调用的输出甚至可能不同,并且确实在某些架构上不同的。
  • @chqrlie 你知道,你可以回答它是一个 UB ,一个初学者不知道这些东西,他会很高兴地编辑他的问题,但你只是投反对票。
猜你喜欢
  • 2014-08-25
  • 2014-04-12
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多