首页 > 解决方案 > 为什么下面编写的两个程序(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 作为输出。

有什么解释吗?

标签: cdata-structuresstructureunions

解决方案


内存中的位用于以不同的方式表示不同的类型。这个答案讨论了最常用于int(32 位二进制补码)和float(IEEE-754 binary32,也称为单精度)的表示,假设填充位或 和 之间的位和字节的不同顺序没有复杂intfloat

对于int,有一个符号位和 31 个值位。31 个值位被解释为二进制数字。符号位表示值-2 31,由符号位表示的值int是符号位的值与二进制数的值之和。

当您将 5 存储在intmemberv.a中时,5 用符号位 0 和值位 0000000000000000000000000000101 表示。当您使用intmember读取它时v.b,这些位的解释方式与它们用于表示 5 的方式相同,因此结果为 5。

当您与floatmember一起阅读时v.b,这些位将使用 for 的方案重新解释float

对于float,有一个符号位s、8 个指数位e和 23 个有效位f,其中ef是解释为二进制数字时的位值。这些位被解释为:

  • 如果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 22f,它是一个安静的 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++ 中,行为未定义。


推荐阅读