结构体我们已经介绍在 自定义类型:结构体 中,今天我们来介绍另一种 自定义类型:联合体
目录
1.联合体的声明
2.联合体的特点
3.联合体大小的计算
4.联合体的应用
5.联合体的一个练习
1.联合体的声明
联合体与结构体类似,它也是一种自定义类型,且也可以存在不同的多种成员。
声明联合体类型的方式也与结构体一样,只是使用的关键字不同,需要用到:union 关键字
union S {
char c1;
int i;
};
2.联合体的特点
1.联合体的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
2.联合体特殊就在于成员之间的内存使用是重叠的,即公用一块空间。
union S {
char c1;
int i;
};
int main() {
//联合变量的定义
union S un = { 0 };
// 下⾯输出的结果是⼀样的吗?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c1));
printf("%p\n", &un);
return 0;
}
输出结果:
0073F874
0073F874
0073F874
内存使用情况
c1存放在了数据起始点,且当你给 int i 赋值完成后,你再对char c1进行修改,那么int i的值也会随之改变
3.联合体大小的计算
- 联合体大小,至少是最大成员的大小
- 当联合体大小不足最大对齐数的整数倍时 ,它的大小就要对齐到最大对齐数的整数倍大小
union S {
short c1[7]; //对齐数为2
int i; //对齐数为4(结构体大小应是它的整数倍)
};
int main() {
union S un = { 0 };
printf("%d\n", sizeof(un));
}
输出结果:16
short c1 [7] 的大小为14,也就是说这个联合体大小至少为14,又由于14不是最大对齐数4的整数倍,所以它的大小应该对齐为16
4.联合体的应用
联合体对比结构体的优势就是节省空间
下面这个例子就可以很好的体现出来:
当我们想省事就会写出以下代码:
struct gift_list
{
//公共属性
int stock_number;//库存量
double price; //定价
int item_type;//商品类型
//特殊属性
char title[20];//书名
char author[20];//作者
int num_pages;//⻚数
char design[30];//设计
int colors;//颜⾊
int sizes;//尺⼨
};
这样的结构体写起来很简单,使用起来也很方便,但是就是有点浪费内存空间
当我们的礼品是书时 ,杯子和衬衫的特殊属性就浪费了
对于礼品清单而言,需要一种物品属性时,另外俩种就不需要了,利用联合体我们就可以写出:
struct gift_list
{
int stock_number;//库存量
double price; //定价
int item_type;//商品类型
union {
struct
{
char title[20];//书名
char author[20];//作者
int num_pages;//⻚数
}book;
struct
{
char design[30];//设计
}mug;
struct
{
char design[30];//设计
int colors;//颜⾊
int sizes;//尺⼨
}shirt;
}item;
};
把每种物品特殊的属性整合起来放在联合体之中,这样就可以做到,你用一种物品的特殊属性时,另外两种物品的特殊属性不占用内存空间
5.联合体的一个练习
在数据在内存中的存储(1)中我们讲过一个小练习:一个程序判断大小端:
int check_sys() {
int a = 1; //a的十六进制为:0x00 00 00 01
char* p = (char*)&a; //指向低地址,也是数据读取的开始
return *p;
}
int main() {
int p = check_sys();
if (p == 1) { //低地址---------->高地址
printf("是小端");// 01 00 00 00
} //低位-------->高位
else { //低地址---------->高地址
printf("是大端");// 00 00 00 01
} //低位-------- > 高位
return 0;
}
那么利用联合体的我们该怎么做到呢?
int check_sys() {
union S {
int i;
char c1;
}un;
un.i = 1;
return un.c1; //返回1是⼩端,返回0是⼤端
}
int main() {
int p = check_sys();
if (p == 1) { //低地址---------->高地址
printf("是小端");// 01 00 00 00
} //低位-------->高位
else { //低地址---------->高地址
printf("是大端");// 00 00 00 01
} //低位-------- > 高位
return 0;
}