存储多个值的联合

Union storing multiple values

本文关键字:存储      更新时间:2023-10-16

代码如下:

#include <iostream>
union mytypes_t {
    char c;
    int i;
    float f;
    double d;
} mytypes;
int main() {
    mytypes.c = 'z';
    mytypes.d = 4.13021;
    mytypes.f = 41.7341;
    cout << mytypes.d << endl;
    return 0;
}

程序输出4.13021(该值声明为双精度类型)。当我尝试输出mytypes.c时,它打印一个空白的正方形(表示一个字符没有正确显示)。

从我对联合的理解来看,它不应该只保存单一类型的单一值吗?如果这是真的,那么它不是一个值为41.7341的浮点数吗?因此将其调用为double或char将抛出错误?

如其他答案所述,所有联合成员占用相同的内存空间。您总是可以将内存解释为基类型,但结果可能出乎意料。

我修改了代码,用十六进制打印出一些细节。您可以看到,随着每个连续的值被赋值,内存将发生变化。当赋值浮点数时,双精度数不会完全改变,因此输出值接近原始值。这只是类型大小和硬件架构的副作用。

作为旁注,为什么使用cout来打印十六进制字符如此痛苦?

#include <iomanip>
#include <iostream>
#include <string.h>
union mytypes_t {
    unsigned char a[8];
    char c;
    int i;
    float f;
    double d;
} mytypes;
int main() {
    memset(&mytypes,0,8);
    std::cout << "Size of the union is: " << sizeof(mytypes) << std::endl;
    mytypes.c = 'z';
    for(int i=0;i<8;i++)
        printf("%02x ", mytypes.a[i]);
    printf("n");
    mytypes.d = 4.13021;
    for(int i=0;i<8;i++)
        printf("%02x ", mytypes.a[i]);
    printf("n");
    mytypes.f = 41.7341;
    for(int i=0;i<8;i++)
        printf("%02x ",mytypes.a[i]);
    printf("n");
    std::cout << mytypes.c << std::endl;
    std::cout << mytypes.d << std::endl;
    std::cout << mytypes.f << std::endl;
    return 0;
}

Size of the union is: 8
7a 00 00 00 00 00 00 00 // The char is one byte
da 72 2e c5 55 85 10 40 // The double is eight bytes
b8 ef 26 42 55 85 10 40 // The float is the left most four bytes
�
4.13021
41.7341

我将对您的类型做一些假设,以便为这个解释提供具体的数字。我假设:char = 1字节,int和float = 4字节,double = 8字节。

现在,它们被保存在内存中的相同位置。通常,如果在结构体中声明int型和float型,int型将占用前4个字节,float型将占用后4个字节。但是保存的数据都是0和1,并且将相同的数字保存为int或float会有不同的0和1的顺序,因为系统对它们的解释不同。例如:int, float.

当您保存到您的联合字段之一时,它将获取与您指定的对应的0和1的正确序列,并将其存储在那里。如果您将15保存到int字段,并将其作为浮点数读取,那么您将得到一个完全不同的数字,因为您强制它以与预期不同的顺序读取该数字。

这一切都归结为@GManNickG在他们的评论中所说的,这是未定义的行为。这个0和1的序列仍然是一个数字,只是不是你想的那个。把它作为一个数字读入并进行计算是完全有效的。这就是为什么使用联合体的东西通常有第二个字段,通常是一个枚举,与联合体分开定义,指定其中保存的类型,以便您知道以后程序的另一部分使用它时要读取哪个字段。

联合的目的是将许多类型分配到同一内存区域。一个联合有内存,你可以根据你在联合中声明的任何类型来表示那个内存。

如果你显式地将一个char类型转换为double类型,反之亦然,你会得到一个错误,不会!联合基本上是类型转换,使用的内存更少。