【C语言】_自定义类型:联合体

发布于:2025-02-10 ⋅ 阅读:(63) ⋅ 点赞:(0)

目录

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;
}

运行结果如下:


网站公告

今日签到

点亮在社区的每一天
去签到