#include <stdio.h>
union p{
int x;
float y;
};
int main()
{
union p p;
p.x = 10;
printf("%f\n", p.y);
return 0;
}
输出:
0.000000
当我尝试编译上述程序时,它没有显示任何警告,
即使在主要功能。为什么printf
无法打印价值10.00000
?
我已经阅读了一些关于 stackoverflow 的相关问题,它解释了printf
在打印整数时没有使用浮点说明符进行类型转换的行为,但我认为这是一个不同的情况。我用float说明符打印浮点数。它应该打印正确的值。谁能解释一下这里发生了什么?
答案 0 :(得分:5)
这是因为int
和float
对象都有不同的二进制表示。假设32位int
和float
,little-endian和IEEE-754表示,你有二进制模式:
0000 1010 0000 0000 0000 0000 0000 0000
即(在浮点数的上下文中)非常小的数字,其使用0.000000
格式说明符打印值为%f
(可以说是printf
四舍五入)。您可以尝试使用%e
f.s.,这会产生另一个输出:
1.401298e-44
C99引入%a
f.s.,它表示存储的浮点数,即2基点浮点数(即尾数和指数):
0x1.4p-146
答案 1 :(得分:4)
你把10整数放入x。 如果你写p.x = 1092616192而不是p.x = 10,你会看到会发生什么 另请阅读https://en.wikipedia.org/wiki/IEEE_floating_point
10在内存中不等于10.f.
答案 2 :(得分:3)
int 和 float ,如果您尝试以科学格式%e
进行打印,则会看到p.f
的以下值:
1.401298E-44
假设IEEE 754 single precision float和4
字节 int ,让我们尝试float convertor来查看有效的十六进制值对于let&# 39;用 IEEE 754 格式表示值40
。
将40
插入转换器会产生十六进制值:
0x42200000
如果我们将此值分配给p.x
:
p.x = 0x42200000;
当您打印40
,see it live时,您会看到值p.y
退出。
关于通过联合的类型惩罚是否是未定义的行为,这一直是一个争论,据我所知它不是,并且在实践中编译器明确支持这种类型的惩罚,这里是the gcc reference explaining its support。