c - 为什么下面编写的两个程序(C 中的联合)的输出存在矛盾?
问题描述
这是第一个代码:
#include<stdio.h>
int main(){
union var{
int a;
int b;
};
union var v;
v.b=10;
v.a=5;
printf("%d", v.b);
return 0;
}
这给出了 5 作为输出。
但是,请考虑以下代码:
#include<stdio.h>
int main(){
union var{
int a;
float b;
};
union var v;
v.b=10.0;
v.a=5;
printf("%f", v.b);
return 0;
}
这给出了 0.000000 作为输出。
有什么解释吗?
解决方案
内存中的位用于以不同的方式表示不同的类型。这个答案讨论了最常用于int
(32 位二进制补码)和float
(IEEE-754 binary32,也称为单精度)的表示,假设填充位或 和 之间的位和字节的不同顺序没有复杂int
性float
。
对于int
,有一个符号位和 31 个值位。31 个值位被解释为二进制数字。符号位表示值-2 31,由符号位表示的值int
是符号位的值与二进制数的值之和。
当您将 5 存储在int
memberv.a
中时,5 用符号位 0 和值位 0000000000000000000000000000101 表示。当您使用int
member读取它时v.b
,这些位的解释方式与它们用于表示 5 的方式相同,因此结果为 5。
当您与float
member一起阅读时v.b
,这些位将使用 for 的方案重新解释float
。
对于float
,有一个符号位s、8 个指数位e和 23 个有效位f,其中e和f是解释为二进制数字时的位值。这些位被解释为:
- 如果e = 0,则表示的值为 (-1) s •2 1-127 •(0+ f /2 23 )。
- 如果 0 < e < 255,则表示的值为 (-1) s •2 e -127 •(1+ f /2 23 )。
- 如果e = 255 且f = 0,则表示的值为 (-1) s •∞。
- 如果e = 255 且f ≠ 0,则表示的值是一个特殊的非数字 (NaN) 值。(如果f的第一位被设置, 2 22 ≤ f,它是一个安静的 NaN。否则,它是一个信令 NaN。)
当位 00000000000000000000000000000101 被解释为 afloat
时,则s为 0,e为 0,f为 5。这符合第一个条件,因此表示的值为 (-1) 0 •2 1-127 •(0+5/ 2 23 ) = 2 -126 •5•2 -23 = 5•2 -149,约为7•10 -45。
当你用 打印这个数字时%f
,它太小了,只打印了“0.000000”。如果使用 打印%g
,输出将是“7.00649e-45”。
请注意,在 C 中,根据 C 2018 6.5.2.3 3 和注释 99,读取除最后写入的成员之外的成员的值会将内存字节重新解释为新类型。在 C++ 中,行为未定义。
推荐阅读
- ios - Swift - 更改幻灯片的大小以删除 tableView 中的按钮
- python - unittest - 比较列表,不考虑顺序
- javascript - Onclick 功能仅显示一秒钟的内容
- javascript - React/Javascript - 需要一个更好的进度条逻辑解决方案
- java - 如何使物体水平移动?
- spring - Spring Data 之后立即执行插入和删除行>
- python - 如何列出 Python 3 中两个嵌套列表之间的区别?
- image - 猜测无损和有损压缩方案来编码图片数据(RGGB 或 YCrCb 或 YCgCo)
- api - 我看不到我的谷歌地图
- git - VS 代码提交撤消