下面的代码每次输出不同的数字..
apples.num 打印 2 这是正确的,而 apples.weight 每次打印不同的数字,它甚至曾经打印出“nan”,我不知道为什么会发生这种情况..
真正奇怪的是 double (apples.volume) 打印出 2.0 ..
有人可以向我解释一下吗?
#include <stdio.h>
typedef union {
short num;
float weight;
double volume;
} Count;
int main(int argc, char const *argv[])
{
Count apples;
apples.num = 2;
printf("Num: %d\nWeight: %f\nVolume: %f\n", apples.num, apples.weight, apples.volume);
return 0;
}
最佳答案
我觉得你不太明白什么是 union 。 union 的成员是重叠的值(换句话说, Count
union 的三个成员共享相同的空间)。
为了演示,假设 short
是 16 位(2 个字节),a float
是 32 位(4 字节)和 double
是 64 位(8 字节),那么 union 体的大小就是 8 字节。在小端格式中,num
成员指的是前 2 个字节,weight
member 指前 4 个字节(包括 num
的 2 个字节),volume member 指完整的 8 个字节(包括 num
的 2 个字节和 weight
的 4 个字节)。
最初,您的 union 包含垃圾,即一些未知的位模式,让我们像这样显示它(以十六进制表示):
GG GG GG GG GG GG GG GG // GG stands for garbage, i.e. unknown bit patterns
如果您设置 num
为 2,则前两个字节为 0x02
0x00
,但其他字节仍然是垃圾:
02 00 GG GG GG GG GG GG
如果您阅读weight
,您只需读取前四个字节,将其解释为 float
,所以float
包含字节
02 00 GG GG
由于浮点值的格式与整数类型完全不同,例如 short
,您无法预测这些字节(即特定的位模式)代表什么。它们不代表浮点值 2.0f,而这正是您可能想要的。实际上,float
的“更重要”部分存储在高字节中,即 weight
的“垃圾”部分,所以它几乎可以是任何东西,包括 NaN
, +infinity
, -infinity
等
同样,如果您阅读volume
,你有一个double
由字节组成
02 00 GG GG GG GG GG GG
这也不一定代表 2.0(尽管,如果碰巧正确的位设置在正确的位置,并且当您显示这样的值时,低位被四舍五入的话,它可能会非常接近) )。
union 并不意味着从 int
进行正确的转换至float
或double
。它们只是为了能够将不同类型的值存储为同一类型,并且从您设置的另一个成员中读取仅仅意味着您正在重新解释一些位,这些位在联盟中作为完全不同的东西存在。您没有转化。
那么如何转换呢?它非常简单,不需要 union :
short num = 2;
float weight = num; // the compiler inserts code that performs a conversion to float
double volume = num; // the compiler inserts code that performs a conversion to double
关于c - 意外的 union 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24834488/