联合体的概念
联合体与之前的结构体、位段、枚举一样,也是自定义类型的一种。这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以联合体也叫共用体)。
联合变量的定义
#include <stdio.h> //联合类型的建立 union U { char i; int n; }; int main() { //联合变量的定义 union U un; //联合变量大小的计算 printf("%u\n", sizeof(un)); return 0; }
联合体的特点
联合体的成员是共用一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的那个成员)。
我们打印出联合变量中成员的地址,具体看一下
#include <stdio.h> union UN { char c1; char c2; int n; double d; }un; int main() { printf("c1 = %p\n", &(un.c1)); printf("c2 = %p\n", &(un.c2)); printf("n = %p\n", &(un.n)); printf("d = %p\n", &(un.d)); return 0; }
运行结果:
其中每个成员都是共用一块内存的,一旦修改了一个成员的值,其他成员的值也会改变。
小结:在同一时间,联合体的成员只能使用一个
联合体的用法
联合体这么独特,那么我们如何使用,又要在什么情况下使用联合体呢?
之前学习过,写一个函数:判断系统是大端存储还是小端存储,接下来就通过这个函数示例一下联合体的使用。
原来的写法
#include <stdio.h> int check_sys() { int i = 1; if (*(char*)&i == 1) return 1;//小端存储 else return 0;//大端存储 } int main() { int ret = check_sys(); if (ret == 1) printf("小端存储\n"); else printf("大端存储\n"); return 0; }
这个写法的思路是:
观察(int*)i和(char*)i,它们是同一个变量,但占用着不同的大小。如果给他们改一下名字
所以我们用联合体的方式来解决这个函数
#include <stdio.h> int check_sys() { union U { char c; int i; }u; u.i = 1; return u.c; //返回1为小端存储 //返回0为大端存储 } int main() { if (check_sys() == 1) printf("小端存储\n"); else printf("大端存储\n"); return 0; }
小结:当需要使用的成员允许使用共用一块空间,且共用一块空间时不会影响设计和使用的时候可以运用联合体来实现。
小结:当需要使用的成员允许使用共用一块空间,且共用一块空间时不会影响设计和使用的时候可以运用联合体来实现。
联合体大小的计算
当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
也就是说,联合体的大小也存在着对齐的情况。
学习过结构体的内存对齐,联合体大小的计算举个例子就很好理解了
#include <stdio.h> union U { char a[5]; int i; }; int main() { printf("%u\n", sizeof(union U)); return 0; }
运行结果:
小练习
//计算下列联合体类型的大小 union U1 { short a[5]; int i; }; union U2 { char c; char arr[5]; }; union U3 { char c; char arr[10]; int i; double d; };
答案: