c - 意外的 union 行为

标签 c floating-point double output unions

下面的代码每次输出不同的数字..
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 进行正确的转换至floatdouble 。它们只是为了能够将不同类型的值存储为同一类型,并且从您设置的另一个成员中读取仅仅意味着您正在重新解释一些位,这些位在联盟中作为完全不同的东西存在。您没有转化

那么如何转换呢?它非常简单,不需要 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/

相关文章:

c - 如何在 while 循环内重置 do while 循环?

c++ - 在编译器上使用 C 和 C++

c++ - 具有字符串输出参数的 WinAPI 函数有多少一致性?

ruby - 为什么 Float 除以零不会在 Ruby 中引发异常?

c++ - 给定一个微秒值,如何准确得到一个timeval结构?/*UPDATE GETTING NEGATIVE VALUE*/

使用 Drop trait 释放 repr(C) 结构的正确习惯用法

javascript - 如何在javascript中格式化 float ?

c++ - 两个 double 可以同时相等和不相等吗?

grails - 用户输入的grails货币值

iOS UIStepper 和 NSUserDefaults - 如何一起管理它们并使用双