联合体
除了结构体和枚举,联合体也是C语言中常见的自定义类型,这种类型定义的变量同样包含一系列的成员,由于这些成员公用同一块空间,所以也叫共用体。
区别于结构体的关键字:struct,枚举的关键字:enum,联合体(共用体)的关键字为 union 。
如下面代码定义了一个联合体类型:
#include<stdio.h>
union Un
{
char c; //1
int i; //4
};
int main()
{
union Un u;
printf("%d\n",sizeof(u)); //4
return 0;
}
联合体的特点
联合体的成员公用同一块内存空间,所以一个联合体的大小至少是最大成员的大小(联合体至少得有能力保存最大的成员)。
再次分析上面的代码:由于联合体成员 char c 和 int i 公用同一块内存空间,所以上面代码联合体定义的变量 u 占4个字节。 这就使得如果变量 c 发生变化,变量 i 也会随之发生改变,所以在实际应用的时候只用两者之一。
用联合体来判断大小端
可以利用联合体来判断大小端字节序,由于联合体成员公用同一块内存空间的特点,如下列代码:令整形成员 i 为1,如果为小端存储(低位字节放在低地址),那么在内存中的存储应为:01 00 00 00,否则为:00 00 00 01
#include<stdio.h>
int check_sys()
{
union Un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main()
{
int i=1;
// 小端 01 00 00 00
check_sys();
if(1 == check_sys())
{
printf("小端\n"); // 小端
}
else
{
printf("大端\n");
}
return 0;
}
运行可知计算机为小段存储字节序。
联合体大小的计算
前面我们已经知道如何计算结构体的大小,那么,联合体的大小的计算与其又有什么不同呢?
看下面这个联合体:
union Un
{
char arr[5]; //5
int i; //4
};
char arr [5] 数组一共占5个字节,int i 占4个字节,由于联合体成员公用同一块内存,所以这个联合体占5个字节,利用下面代码来检验我们的判断:
#include<stdio.h>
union Un
{
char arr[5];//5
int i;//4
};
int main()
{
printf("%d\n",sizeof(union Un)); // 8
return 0;
}
打印结果为8,并不是我们判断的5字节。
原来,联合体计算大小的时候也要考虑对齐。上面代码中:最大一个成员 char arr [5] 占用了5个字节,考虑到联合体有对齐的特点,对 char 类型,对齐数是1;对 int 类型,对齐数是4,联合体的大小应该是最大对齐数的倍数,所以在我们推断的基础上再扩展3个字节的空间,即该联合体的大小为8字节。
注意:联合体的大小不一定是联合体最大成员的大小。