C 面试问题打印浮点数

C 面试问题打印浮点数,c,floating-point,printf,C,Floating Point,Printf,以下程序的输出是什么?为什么 #include <stdio.h> int main() { float a = 12.5; printf("%d\n", a); printf("%d\n", *(int *)&a); return 0; } #包括 int main() { 浮点数a=12.5; printf(“%d\n”,a); printf(“%d\n”、*(int*)&a); 返回0; } 我的编译器打印0和10952376

以下程序的输出是什么?为什么

  #include <stdio.h>
  int main()
  {
   float a = 12.5;
   printf("%d\n", a);
   printf("%d\n", *(int *)&a);
   return 0;
  }
#包括
int main()
{
浮点数a=12.5;
printf(“%d\n”,a);
printf(“%d\n”、*(int*)&a);
返回0;
}
我的编译器打印0和1095237632。为什么?

这是因为(参见标准)

简言之,在IEEE 755表示法中,当解释为整数时,使12.5浮点值的一组位将为您提供奇怪的值,该值与12.5值没有太多共同之处


printf(“%d\n”,a)
写入
0
,这是错误printf调用的内部未定义行为。

a
引用的内存包含处理器用于表示12.5的位模式。它是如何表示的:。它看起来像什么。当解释为int时是什么?1095237632

当你不进行铸造时,为什么会得到不同的值?我不是100%确定,但我猜这是因为编译器可以使用一个在不同位置传递浮点参数的函数,而不是整数,所以当printf试图找到字符串后的第一个整数参数时,那里没有可预测的内容。

(或者更可能的是,正如@Lindydancer所指出的,浮点位可以在int的“正确”位置传递,但由于它们首先通过扩展零提升为双精度表示,printf期望第一个int的位置有0。)

在这两种情况下,都传递表示浮点值的位,并以十进制打印它们。第二种情况是简单情况,这里的输出与浮点数的基本表示形式相同。(这假设调用约定指定
float
的值与
int
的传递方式相同,这是不保证的。)

但是,在第一种情况下,当您将
float
传递给像
printf
这样的vararg函数时,它将升级为
double
。这意味着传递的值将是64位,而
printf
将拾取其中的一半(或者可能是垃圾)。在您的例子中,它显然拾取了32个最低有效位,因为在
浮点
双精度
转换后,它们通常都是零


为了明确起见,问题中的代码不是有效的C,因为向
printf
传递与格式说明符不匹配的值是非法的。

你怎么看?我猜&a应该返回a的地址,该地址被转换为int指针(而不是浮点指针)然后指针被解除引用以访问a。此外,
*(int*)&a
违反了严格的别名规则,因此,如果由于程序的其余部分而没有发生任何事情,则可能因此发生任何事情。谢谢您的回答。我正在努力学习C语言,但我在使用指针类型转换时总是遇到问题。在位级别,当您在类型a的指针与相关/不相关类型之间进行强制转换时会发生什么?(我说的是严格意义上的C类型转换)。指针指向的内存内容保持不变,但访问方式不同?大多数关于指针的文献都涉及指针算法,以及对转换和数组等的概述,但它们都不够深入……看不出这是如何回答问题的question@DavidHeffernan:问题是“为什么”,答案是因为这就是12.5是如何使用IEEE 754编码的。答案中的标准规范没有复制粘贴的意义。
printf(“%d\n”,a)打印0。为什么?@DavidHeffernan:因为这是错误的printf调用的内部未定义行为。绝对清楚,然后是混合含义:)当然“无效C”@tinman,很好,我已经用缺少的“不”更新了答案——谢谢!我认为林迪丹瑟的论点实际上是正确的;wiki同意浮动总是升级为双精度(因此格式的说明符都是双精度的),这就是生成零的原因。参数通过堆栈而不是寄存器传递。编译器根本无法进行优化,因为函数可以接受任何类型。在这种情况下,Lindydancer可能是正确的,至少对于Windows编译器是这样。但是,请参见“”中的第3.5.7节和表3.32,其中描述了64位Linux的约定。它声明“假设所有参数都在堆栈上传递…[不]在AMD64体系结构上工作,因为一些参数在寄存器中传递”,并显示用于浮点的寄存器集与用于一般用途的寄存器集不同。所以它可能以我的方式发生+链接为1。这一定会在varargs.cpp中产生一些非常复杂的代码。它将不得不做一些组合,包括查看堆栈下面的内容,以及在解析格式字符串时检查各种寄存器。