关键字union,又称为联合体、共用体,联合体的声明和结构体类似,但是它的行为方式又和结构体不同,这里的行为方式主要指的是其在内存中的体现,结构体中的成员每一个占据不同的内存空间,而联合体中的所有成员共用的是内存中相同的位置。
简单看下区别:
1 struct MyStruct
2 { 3 double a; 4 int b; 5 char c; 6 }; 7 struct MyStruct value;
1 union MyUnion
2 { 3 double a; 4 int b; 5 char c; 6 }; 7 union MyUnion value;
同样是定义变量value;内存空间占用情况如下:
可以看出,结构体变量中3个成员相当于3个人,每个人必须要住一间屋子,优点是空间包容性强,但是内存空间必须全部分配,不管房子住不住人。联合体变量3个成员,它们可以共用一间屋子,但是每个屋子同一时间只能容纳一个成员,因此不够包容,成员是互斥的,但是可以大大节省内存空间。
要注意的是,联合体的长度大小为最大的成员的大小,在本例中即value.a的大小。并不是单指数据类型,若在MyUnion定义了数组char c[10],则此时该联合体变量value大小为10个字节。
以上简单的了解了下union的基本定义,在实际应用中我们一般都使用结构体来定义数据组合而成的结构型变量,而在各数据类型各变量占用空间差不多并且对各变量同时使用要求不高的场合(单从内存使用上)也可以灵活的使用union。
-
1、变量的初始化
在初始化的时候,只应对一个成员进行初始化即在初始化列表中只有一个初始值。原因就是联合体的所有成员共用一个首地址,在默认情况下,会将这个初始值初始化给联合体变量的第一个成员。
1 union MyUnion
2 { 3 double a; 4 int b; 5 char c; 6 }; 7 //为第一个成员初始化 8 union MyUnion un1 = {5.0f}; 9 //错误初始化,不能为多个成员初始化 10 union MyUnion un1 = {5.0f, 10}; 11 //对其它位置的成员进行初始化,则可以通过指定初始化方式 12 union MyUnion un1 = {.b = 10}; 13 //与结构体一样,也可以将一个联合体变量作为初始值,直接初始化给同类型的另一个联合体变量 14 union MyUnion un2 = un1;
-
2、数据位操作
1 #include<stdio.h>
2 typedef struct
3 {
4 unsigned char bit0:1; 5 unsigned char bit1:1; 6 unsigned char bit2:1; 7 unsigned char bit3:1; 8 unsigned char bit4:1; 9 unsigned char bit5:1; 10 unsigned char bit6:1; 11 unsigned char bit7:1; 12 }bitValue; 13 14 typedef union 15 { 16 unsigned char bytedata; 17 bitValue bitdata; 18 }regValue; 19 20 int main() 21 { 22 regValue data; 23 data.bytedata= 0x5A; 24 printf("%d",data.bitdata.bit5); //读取第6位 25 data.bitdata.bit7 = 1; //修改第8位 26 return 0; 27 }
可以看出,通过访问和修改联合体中的定义bitdata成员,可以间接的访问和修改定义的bytedata的值,这可以用在嵌入式的寄存器位操作上。
比如我们分别定义电视和空调的属性:
1 struct tvFeature //电视属性
2 {
3 char *logo; //品牌
4 int price; //价格
5 int screensize //屏幕尺寸
6 int resolution //分辨率
7 }tvFeature; 8 struct tvFeature tvfeature; 9 10 struct airFeature //空调属性 11 { 12 char *logo; //品牌 13 int price; //价格 14 int coldcapacity;//制冷量 15 int hotcapacity;//制热量 16 }airFeature; 17 struct airFeature airfeature;
可以看出电视和空调有相同的属性,也有各自特有的属性。我们可以使用家用电器的数据结构统一定义。但是这样用统一的数据结构,定义电视和空调的变量之间耦合会增加很多,对于tvfeature和airfeature各自来说用不到的属性也会浪费内存空间。
1 struct homeappliancesFeature //电器属性
2 {
3 char *logo; //品牌
4 int price; //价格
5 int screensize //屏幕尺寸
6 int resolution //分辨率
7 int coldcapacity;//制冷量
8 int hotcapacity;//制热量
9 }homeappliancesFeature; 10 11 struct homeappliancesFeature tvfeature; 12 struct homeappliancesFeature airfeature;
因此可以用union来解决问题:
1 struct tvFeature //电视属性
2 {
3 int screensize //屏幕尺寸
4 int resolution //分辨率
5 }tvFeature; 6 struct airFeature //空调属性 7 { 8 int coldcapacity;//制冷量 9 int hotcapacity;//制热量 10 }airFeature; 11 12 struct homeappliancesFeature //电器属性 13 { 14 char *logo; //品牌 15 long country; //国家 16 union 17 { 18 struct tvFeature tvST; 19 struct airFeature airST; 20 }; 21 }; 22 struct homeappliancesFeature tvfeature; 23 struct homeappliancesFeature airfeature;
如上我们只需一个结构体,就可以解决电视和空调的属性不同问题;struct tvFeature tvST和struct airFeature airST共用一块内存空间,定义变量时,可以访问各自的特有属性,这样就解决了内存浪费和变量耦合高的问题。
-
4、数据复制
例如串口数据发送时,可以直接使用数据