【C语言】_自定义类型:联合体
目录
1. 联合体类型的声明
2. 联合体的特点
3.1 成员变量共用一块内存
3.2 由于共用内存导致的相关性
4. 结构体与联合体对比
5. 联合体大小的计算
6. 联合体的应用
6.1 多类型特定属性组结构体
6.1.1 设计方案1:采用纯结构体
6.1.2 设计方案2:结构体+联合体
6.2 判断大小端
6.2.1 方法1:使用指针类型的解引用权限原理
6.2.2 方法2:使用联合体的共用内存原理
1. 联合体类型的声明
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
union Un {
char c;
int i;
};
int main() {
union Un u = { 0 };
printf("%d\n", sizeof(u));
return 0;
}
2. 联合体的特点
1、联合体与结构体类似,联合体也是由一个或多个成员构成,这些成员可以是不同类型。
2、编译器只为最大成员分配足够的内存空间;
3、联合体的特点:所有成员共用一块内存空间。故联合体也称共同体;
3. 联合体的内存分配
3.1 成员变量共用一块内存
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
union Un {
char c;
int i;
};
int main() {
union Un u = { 0 };
printf("%d\n", sizeof(u));
printf("&u = %p\n", &u);
printf("&u.c = %p\n", &u.c);
printf("&u.i = %p\n", &u.i);
return 0;
}
运行结果及内存分配如下:
3.2 由于共用内存导致的相关性
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
union Un {
char c;
int i;
};
int main() {
union Un u = { 0 };
u.i = 0x11223344;
u.c = 0x55;
printf("%x\n", u.i);
return 0;
}
单步调试,查看内存实际存储:
4. 结构体与联合体对比
1、关于定义与关键字等:
结构体 | 联合体 | |
关键字 | struct | union |
成员 | 多个不同类型成员 | 多个不同类型成员 |
内存分配 | 每个成员都有自己独立的空间 | 所有成员共用同一块内存空间 |
2、关于内存分配:
5. 联合体大小的计算
1、联合体的大小至少是最大成员的大小;
2、当最大成员大小不是最大对齐数的整数倍时,联合体的大小须对齐到最大对齐数的整数倍;
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
运行结果如下:
分析如下:
(1)对于联合体union Un1而言:
数组c有5个char类型的元素,共占5个字节;整型变量i占4个字节;
最大对齐数 = max { sizeof ( char ) , sizeof ( int ) } = max {1, 4 } = 4;
union Un1大小至少为5,且须为4的整数倍,故大小为8;
(2)对于联合体union Un2而言:
数组c有7个short类型的元素,共占14个字节;整型变量i占4个字节;
最大对齐数 = max { sizeof ( short ),sizeof ( int ) } = max { 2, 4 } = 4;
union Un2大小至少为14,且须为4的整数倍,故大小为16;
6. 联合体的应用
6.1 多类型特定属性组结构体
假设当前有图书、杯子、衬衫三种商品,对于每种商品都有库存量、价格、商品类型属性;
不同商品类型,也会有其他特定信息:
图书还需书名、作者、页数属性;杯子还需设计属性;衬衫还需设计、颜色、尺寸属性;
6.1.1 设计方案1:采用纯结构体
struct goods
{
//公共属性
int stock; //库存量
double price; //定价
int type; //商品类型
//特殊属性
char title[20]; //书名
char author[20]; //作者
int pages; //⻚数
char design[30]; //设计
char colors[20]; //颜⾊
int sizes; //尺⼨
};
若采用纯结构体作为商品的自定义类型,则由于特殊属性的存在须在结构体内包含所有商品所需的所有属性,造成一定空间浪费;
6.1.2 设计方案2:结构体+联合体
对于每一个商品,它只属于一种商品类型,故而一种商品只会有一组特殊属性;
采用以下设计思路:
先列出公共属性,将各商品的特殊属性设计为结构体,再作为联合体的成员变量:
struct goods
{
int stock; //库存量
double price; //定价
int type; //商品类型
union Un {
struct Book
{
char title[20]; //书名
char author[20]; //作者
int pages; //⻚数
}book;
struct Mug
{
char design[30]; //设计
}mug;
struct Shirt
{
char design[30]; //设计
char colors[20]; //颜⾊
int sizes; //尺⼨
}shirt;
}item;
};
6.2 判断大小端
6.2.1 方法1:使用指针类型的解引用权限原理
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int check_sys_bypointer() {
int n = 1; // 0x00 00 00 01H
return *(char*)&n; // 低地址存低字节数据->小端
}
int main() {
// 小端返回1,大端返回0
int ret = check_sys_bypointer();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
运行结果如下:
6.2.2 方法2:使用联合体的共用内存原理
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int check_sys_byunion() {
union U {
char c;
int i;
}u;
u.i = 1; // 0x00 00 00 01H
return u.c; // 返回4字节中的第1个字节(返回低地址处的值)
}
int main() {
// 小端返回1,大端返回0
int ret = check_sys_byunion();
if (ret == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
运行结果如下: