C++ 联合、共同体union

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yyl424525/article/details/89326103

1.联合union和结构体struct的区别

“联合”与“结构”有一些相似之处:都是用户自定义类型,都由多个成员组成,成员的类型可以不同。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度
应该说明的是,这里所谓的共享不是指把多个成员同时装入一个联合变量内,而是指该联合变量可被赋予任一成员值,但每次只能赋一种值,赋入新值则覆盖旧值。

利用联合,可以将程序中使用范围不同的变量放在一个联合中,让它们共享存储单元,提高内存的利用率。一个联合中常有多个成员,这些成员的类型可以相同也可以不同。

结构变量可以作为函数参数,函数也可返回指向结构的指针变量。而联合变量不能作为函数参数,函数也不能返回指向联合的指针变量。 但可以使用指向联合变量的指针,也可使用联合数组。

2.联合和联合变量定义

当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。
在C Programming Language一书中对于联合体是这么描述的:
1)联合体是一个结构;
2)它的所有成员相对于基地址的偏移量都为0;
3)此结构空间要大到足够容纳最"宽"的成员;
4)其对齐方式要适合其中所有的成员;
演示代码如下:

#include<iostream>
using namespace std;

union U1
{
    int n;
    char s[11];
    double d;
};

union U2
{
    int n;
    char s[5];
    double d;
};

int main()
{
    U1 u1;
    U2 u2;
    cout<<sizeof(u1)<<'\t'<<sizeof(u2)<<endl;
    cout<<"u1各数据地址:\n"<<&u1<<'\t'<<&u1.d<<'\t'<<&u1.s<<'\t'<<&u1.n<<endl;
    cout<<"u1各数据地址:\n"<<&u2<<'\t'<<&u2.d<<'\t'<<&u2.s<<'\t'<<&u2.n<<endl;
}

输出结果:
16      8
u1各数据地址:
0x6ffe40        0x6ffe40        0x6ffe40        0x6ffe40
u1各数据地址:
0x6ffe30        0x6ffe30        0x6ffe30        0x6ffe30

上述代码中:
对于U1联合体,s占11字节,n占4字节,d占8字节,因此其至少需1字节的空间。然而其实际大小并不是11,用运算符sizeof测试其大小为16。这是因为这里存在字节对齐的问题,11既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。
从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,即其大小必须满足两个条件:
1)大小足够容纳最宽的成员;
2)大小能被其包含的所有基本数据类型的大小所整除。
对于U2联合体,同理知道,用运算符sizeof测试其大小为8。

从结果中还可以发现,联合体中的各数据的存储地址都是相同的。

下面再研究具体每种类型数值都存储在哪里?

    #include<iostream>  
    using namespace std;  
      
    union U  
    {  
        unsigned int n;  
        unsigned char s[4];  
    };  
      
    int main()  
    {  
        U u;  
        u.n = 0xf1f2f3f4;  
        cout<<hex<<u.n<<'\t'<<&u.n<<endl;  
        cout<<hex<<(int)u.s[0]<<'\t'<<(void*)&u.s[0]<<endl;  
        cout<<hex<<(int)u.s[1]<<'\t'<<(void*)&u.s[1]<<endl;  
        cout<<hex<<(int)u.s[2]<<'\t'<<(void*)&u.s[2]<<endl;  
        cout<<hex<<(int)u.s[3]<<'\t'<<(void*)&u.s[3]<<endl;  
    }  
    
输出结果:
f1f2f3f4        0x6ffe30
f4      0x6ffe30
f3      0x6ffe31
f2      0x6ffe32
f1      0x6ffe33

上述代码中,联合体U中,n占4字节,s[4]也占4字节。故联合体共占4字节。
这说明,内存中数据低位字节存入低地址,高位字节存入高地址,而数据的地址采用它的低地址来表示

猜你喜欢

转载自blog.csdn.net/yyl424525/article/details/89326103