一、联合体(共用体)
和结构体一样,联合体也是由一个或者多个成员组成,这些成员可以是不同的类型。、
联合体和结构体的不同的就是,其所有成员共用一块内存空间,所以联合体也称为共用体,那么因为其是所有成员共用一块内存空间,所以其空间大小应该是最大的成员,而且当我们对其中一个成员赋值的时候,其他成员的值也会发生变化。
下面我们开始对联合体进行学习。
1、联合体的声明
联合体的声明和结构体的声明是类似的,结构体声明的时候是使用关键字struct,而联合体的声明则是使用union关键字。
其声明如下:
其变量创建的方式和结构体也是类似的,其变量的数据类型就是其关键字+名字。
如下:
2、联合体的特点
联合体的成员都是使用同一块内存空间的,那么一个联合体变量的大小,至少也是其最大成员的大小。
运行结果:
可以看到上面代码中,联合体的成员的地址都是一样的,而且 联合体自己和成员的地址也是一样的,那么可以说明其是使用的一块空间。
下面我们再看如果对一个成员进行修改会不会影响另外一个成员。
代码如下:
我们试着分析上面的代码,首先我们对这个联合体变量a进行初始化0,然后我们对这个变量的成员i进行赋值,对其赋了一个16进制的11223344,然后将16进制数55赋值给成员a, 那么如果两个成员使用的是同一块空间,那么我们在对a进行赋值的时候,那么i应该会跟着发生改变。
那么在内存中,vs是小端字节序的存放,那么其在内存的存放是:44 33 22 11,然后再对a进行赋值,那么给它赋值的55就应该会将原来存放44的空间进行修改了。
下面我们看看运行结果:
可以看到其就是将44的位置的空间存放的内容修改了,这个结果进一步可以证明联合体的成员是共用的一个空间。
3、联合体大小的计算
要计算其大小,那么我们就需要其在内存中是如何存储的。
其存储的规则如下:
1、联合体的大小至少是最大成员的大小,因为我们至少要保证其每个成员都可以存储。
2、当最大的成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
首先我们看第一个联合体Un1,先看第一个规则,其最大的成员是字符数字c其大小为5,那么其此时的空间大小至少为5,然后我们再看第二个规则,这个联合体的最大对齐数应该为4那么其最终的大小应该为4的倍数,那么此时这个联合体的大小应该为8。
那么同理,第二个联合体,其第一个短整型,那么其这个短整型数组的大小为14,然后其对齐数为2,然后第二个成员的对齐数为4,那么最终的这个联合体的大小应该为4的倍数,那么最终这个联合体的大小有关应该为16。
下面我们看看运行结果:
4、练习
使用联合体,判断当前的机器是大端字节序还是小端字节序。
前面我们学习过大小端字节序,如果忘记了可以往前看。
前面我们是使用强制类型转换,将一个整型指针强制转换为字符指针,然后看其结果是不是为1,如果是1那么就是小端字节序,是0就是大端字节序。
下面我们看看在联合体中如何实现:
其实和上面的大差不差,上面的本质上是在同一块地址上进行操作,那么我们联合体刚刚好就契合这一点,那么我们可以创建一个联合体,其成员有一个整型,一个字符型。
然后我们先对整型成员进行赋值,那么此时其实也是对这个字符型成员也进行了赋值,那么我们此时判断这个字符型成员是否是1,如果是1那么就是小端,如果是0那么就是大端。
代码如下:
运行结果:
5、相同成员在结构体和联合体对比
下面我们看看结构体和联合体在内存上的区别:
下面我们画图来看看其在内存中的存放:
通过上面的图可以看到,联合体使用的空间是非常少的。
6、联合体的使用
通过上面的学习我们知道了联合体是可以节省空间的,那么我们该在什么样的情况下使用联合体呢?
因为联合体中的成员,当对其中一个成员进行修改的时候,都可能会影响其他的成员。
那么我们可以想到,联合体中的成员,在实际上应该是有一些共同的内容的,比如说我们对一个物品进行描述,这个联合体中的成员只需要出现一次即可。
例如:
我们现在需要搞一个活动,然后需要上线一个礼品兑换单,礼品兑换单中有三个:图书,杯子,衬衫。
然后每一种商品的相关信息如下:
图书:书名、作者、页数。
杯子:设计。
衬衫:设计、颜色、尺寸。
那么我们可以直接使用结构体:
上面的话就是一窝蜂将这些属性直接创建在结构体中,这样会使得这个结构体占用的内存比较大,浪费空间。而且上面的内容中有的内容是不常用的。
比如说图书,其在颜色和尺寸的这些内容是不咋用的,那么其实我们可以将一些共同的属性单独写出来。
如下:
我们先将三者都有的库存量,定价,商品类型单独写出来,然后每种商品的特殊属性就使用联合体存放。
然后我们在对某个礼品进行描述的时候,在同个时空的时候只会使用一个。
二、枚举
1、枚举类型的声明
枚举顾名思义就是⼀⼀列举。
把可能的取值⼀⼀列举。
⼀周的星期⼀到星期⽇是有限的7天,可以⼀⼀列举
性别有:男、⼥、保密,
也可以⼀⼀列举 ⽉份有12个⽉,
也可以⼀⼀列举
三原⾊,也是可以一一列举
所以枚举就是将这些可能的情况一一列举出来。
要注意的是枚举的关键字是enum。
下面我们将上面提到的使用枚举实现一下:
以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫 枚举常量 。
这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。
2、 枚举类型的优点
为什么使⽤枚举? 我们可以使⽤ #define 定义常量,为什么⾮要使⽤枚举?我们看看枚举的优点: 1. 增加代码的可读性和可维护性
2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
3. 便于调试,预处理阶段会删除 #define 定义的符号
4. 使⽤⽅便,⼀次可以定义多个常量
5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤
3、枚举的使用
我们先创建一个枚举,然再对其赋值。
上面就是我们枚举的使用了。