目录
1.定义
和结构体有所不同,顾名思义:所有成员联合使用同一块内存空间,因此也叫共用体
注:编译器只为最大的成员分配足够的内存空间;如果不符合对齐数,则会增加一部分空间(有关联合体的大小计算见第6点)给联合体其中一个成员赋值,其他成员的值也跟着变化
2.格式
union 联合体标签
{
//......
};
3.例题
求下列代码的执行结果
#include <stdio.h>
union U
{
char a;
int b;
};
int main()
{
printf("%zd\n", sizeof(union U));
union U u;
printf("%p\n", &u);
printf("%p\n", &u.a);
printf("%p", &u.b);
return 0;
}
答案速查
分析
01.printf("%zd\n", sizeof(union U));
编译器只为最大的成员分配足够的内存空间
char a 对齐数为1,int b对齐数为4(注:联合体对齐数的计算方法同结构体的),因此为a和b分配4字节的空间
02.printf("%p\n", &u); & printf("%p\n", &u.a); & printf("%p", &u.b);
所有成员联合使用同一块内存空间,因此取地址的结果一样
4.练习
求下列代码执行后,联合体在内存中存储的数据
#include <stdio.h>
union U
{
char a;
int b;
};
int main()
{
union U u;
u.b = 0x12345678;
u.a = 0x99;
return 0;
}
答案速查
VS2022按小端序存储
因此为99 65 43 21
分析
运行环境x86+debug
下断点(F9)至u.a = 0x99;,内存窗口输入&u
执行至return 0;
5.相同成员的联合体和结构体的对比
union U
{
char a;
int b;
};
struct S
{
char a;
int b;
};
6.联合体的大小计算
2条规则
1.联合的大小至少是最大成员的大小
2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍(多数人往往会忽视第2点)
例如:
求下列代码的执行结果
#include <stdio.h>
union U
{
char a[5];
int b;
};
int main()
{
printf("%zd", sizeof(union U));
return 0;
}
答案速查
分析
如果不考虑第二点规则,答案应该是5
如果考虑第二点规则,
char a[5]; 自身对齐数:1,VS默认对齐数:8,所以对齐数为1
int b; 自身对齐数:4,VS默认对齐数:8,所以对齐数为4
a[5]与b的最大对齐数为4
所以联合体的大小至少为4的整数倍(4,8,12,...,4k),大于5且最近的4整数倍的数为8
练习
求下列代码的执行结果
#include <stdio.h>
union U
{
short a[7];
int b;
};
int main()
{
printf("%zd", sizeof(union U));
return 0;
}
答案速查
分析
short a[7]; 自身对齐数:2,VS默认对齐数:8,所以对齐数为2
int b; 自身对齐数:4,VS默认对齐数:8,所以对齐数为4
如果不考虑第二点规则,答案应该是14(7*2=14)
如果考虑第二点规则,short a[7];与int b;的最大对齐数为4,所以联合体的大小至少为4的整数倍(4,8,12,...,4k),大于14且最近的4整数倍的数为16
7.联合体的优点
如果一些变量既有公共属性,又有各自的联合属性,可以把公共属性单独写出来,剩余属于各自本身的属性使用联合体起来(联合体内嵌结构体)
这样可以节省空间
8.匿名联合体
同匿名结构体,见文63.【C语言】再议结构体(上)