【C++】union

目录

概述

定义

互斥赋值

访问权限

为成员指定长度

union中定义结构体


 

我的理解(如果这部分看不懂,先看下面再来看这里)

union联合,内部只能是结构体(struct)和普通变量类型(如int等),然后以其中一个占内存最大的变量的大小S就是该union所占内存的大小。意味着union联合体内所有变量共享这块内存S。比如union体

union Token{
   char cval;
   int ival;
   double dval;
};

在内存就这如下图所示:

 在union被声明好后,union中的3个变量就对应着8个字节的内存,只要给其中一个赋值,其他变量就可以直接使用的,只要到他对应的内存位置取值就行。

概述

定义

union即为联合,它是一种特殊的类。通过关键字union进行定义,一个union可以有多个数据成员。例如

union Token{
   char cval;
   int ival;
   double dval;
};

以上代码定义了一个名为Token的联合,该联合中包含了3个数据成员。

互斥赋值

在任意时刻,联合中只能有一个数据成员可以有值。当给联合中某个成员赋值之后,该联合中的其它成员就变成未定义状态了。

Token token;
token.cval = 'a';
token.ival = 1;
token.dval = 2.5;

以上代码定义了联合Token的一个变量token,此时token所占内存的数据如图1所示。

                                                                                  图1 token所占内存数据

红色方框内的数据即为token所占内存数据。因为token中长度最大的变量是double类型,所以token的长度是8个字节。

之后首先为token的变量cval赋值,此时token所占内存的数据如图2所示。

                                                                                   图2 token所占内存数据

此时,token所占内存的第一个字节的值变为0x61,即字符’a’。

接下来为token的变量ival赋值,此时token所占内存的数据如图3所示。

                                                                                   图3 token所占内存数据

此时,token所占内存的前四个字节变为0x00000001,即为数字1。在对token的ival赋值之后,cval的值就变为了0x01,实际上就没有意义了。

最后,为token的变量dval赋值,此时token所占内存的数据如图4所示。

                                                                                     图4 token所占内存数据

此时,token所占内存的八个字节都有了相应的值。在对token的dval赋值之后,cval的值变为了0x00,而ivale的值变为了0x00000000,都没有了实际意义,也就是之前提到的未定义状态。

访问权限

联合可以为其成员指定public、protected和private等访问权限,默认情况下,其成员的访问权限为public。在“1.1 定义”中定义的联合Token,其三个成员的访问权限均为public。

为成员指定长度

在“1.2 互斥赋值”中提到,联合的存储空间至少能够容纳其最大的数据成员。也可以为联合的成员指定长度。通过冒号操作符来实现成员长度的指定。
 

union U {
unsigned short int aa;
struct {
unsigned int bb : 7;//(bit 0-6)
unsigned int cc : 6;//(bit 7-12)
unsigned int dd : 3;//(bit 13-15)
}; 
} u;

以上代码定义了一个名为U的联合,并且定义了U的变量u。联合U包含两个成员,一个是unsigned short int类型的变量,其大小为2个字节;另一个是一个自定义结构,该自定义结构中包含了3个unsigned int类型的变量。需要注意的是,每个unsigned int类型的变量的大小并不是默认的4个字节,而是通过冒号操作符指定了其大小,该大小的单位是比特。所以,联合u的大小是2个字节。

之后,对联合u中的aa进行赋值

u.aa = 0xE07F;

此时,联合u所占的内存数据如图5所示。

                                                                                      图5 联合u所占内存数据

此时,u.bb所处的位置是0-6比特;u.cc所处的位置是7-12比特;u.dd所处的位置是13-15比特,如图6所示。

                                                                                           图6 联合u的结构

所以,此时u.bb的值是127;u.cc的值是0;u.dd的值是7。

union中定义结构体

为什么只讲结构体的例子呢?

因为除了普通类型和结构体,其他都不行。

例一 

#include <stdio.h>
union
{
    int i;
    char x[2];
}a;

void main()
{
    a.x[0] = 10;
    a.x[1] = 1;
    printf("%d", a.i);
}

 答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)  

main函数中对union变量a中的数组X进行赋值,由于会分配4个字节的空间,但是x只占用了两个字节的空间,而且在赋值时从低地址开始,

所以a在内存中的分布是这样的:

 

从高位到低位读也就是0x00 00 01 0A  注意:低位两个字节是01 0A 不是10 A0(我就是当时把这个搞错了。。)

当输出a.i时,由于占用同样一块内存,所以会读出四个字节,转换为10进制也就是266

 

还有一个误区就是:10在16进制中是A,但是A只有4位,但是一个字节有八位,在高位添0,所以10在内存中是0A,而不是A(当时我也搞错了。。。)

 

例二

#include <stdio.h>
void main()
{
    union { /*定义一个联合*/
        int i;
        struct { /*在联合中定义一个结构*/
            char first;
            char second;
        }half;
    }number;
    number.i = 0x4241; /*联合成员赋值*/
    printf("%c%c\n", number.half.first, number.half.second);
    number.half.first = 'a'; /*联合中结构成员赋值*/
    number.half.second = 'b';
    printf("%x\n", number.i);
}

答案: AB (0x41对应'A',是低位;Ox42对应'B',是高位)  

6261 (number.i和number.half共用一块地址空间)

 

union中有两个变量,一个int i 占四个字节,一个结构体,占两个字节,所以这个union占有四个字节的内存

当给i赋值后内存中是这样的:

 

当输出结构体中的成员时:

printf("%c%c/n", number.half.first, mumber.half.second);

第一个字节(也就是0x41)被赋给 number.half.first,第二个字节(0X42)被赋给 number.half.second

于是分别输出了AB

 

当给结构体中的元素赋值后:

number.half.first='a'; /*联合中结构成员赋值*/
number.half.second='b';

 

‘a‘=0x61,’b‘=0x62

内存中是这样的:

 

当输出i的时候,把四个字节都读出来

用十六进制输出就是0X00 00  62 61也就是6261

 

例三

bool checkCPU()
{
    union w
    {
        int a;
        char b;
    } c;
    c.a = 1;
    printf("%p", &c.a);
    return (c.b == 1);
}

void main()
{
    if (checkCPU())
    {
        printf("This is little endian");
    }
}

大小端不懂,可以参考这篇博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值