【C语言】联合体与结构体如何巧妙配合使用节省内存空间?

本篇文章目录

  • 1. 联合体的特点
  • 2. 计算联合体占用内存大小
  • 3. 利用联合体的特点判断当前机器是以什么字节序顺序存储数据?
  • 4. 联合体什么时候使用?

1. 联合体的特点

联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

#include 
union Un
{
	char c;
	int i;
};
int main() {
	union Un un;
	printf("%d\n", sizeof(un)); // 4
	return 0;
}

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。


#include 
union Un
{
	char c;
	int i;
};
int main() {
	union Un un;
	printf("%p\n", &un);
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
	
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);
	return 0;
}

【C语言】联合体与结构体如何巧妙配合使用节省内存空间?_第1张图片

  1. 因为是共用一块内存空间,所以对于起始地址而言三者都是一样的。
  2. 0x11223344实际上在内存中是以小端字节序存储:44 33 22 11,联合体的内存空间对每个成员而言是共用的,只是每个成员能访问的大小根据自身的数据类型决定,i能使用4个字节,c则能使用1个字节,结果为11223355的原因想必不难理解。

2. 计算联合体占用内存大小

  1. 联合的大小至少是最大成员的大小
  2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
#include 
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;
}

在这里插入图片描述
Un1的最大对齐数不是5!char数组实际上只是算作5个char类型变量。i的大小作为对齐数,但却不是最大成员,char数组才是最大成员,4个字节存不下char数组(5个字节),所以要对齐到4的倍数8才能存下。Un2相同道理。

3. 利用联合体的特点判断当前机器是以什么字节序顺序存储数据?

#include 
union Un1
{
	char c;
	int i;
};
int main() {
	union Un1 un;
	un.i = 1; 
	if (un.c == 1) {
		printf("小端字节序");
	} 
	else {
		printf("大端字节序");
	}
	return 0;
}

在这里插入图片描述

1在内存中如果是以小端字节序存储的,那么是这个样子:00000001 00000000 00000000 00000000(十六进制:01 00 00 00)。c是char类型,只能访问1个字节大小的数据,如果访问到的值是1,说明当前机器就是小端字节序存储数据。

4. 联合体什么时候使用?

某些成员不会同一时间使用,这时使用联合体是可以节省空间的。

比如某个商店有一个活动要上线一个礼品兑换单,兑换单中有三种商品:图书、杯子、衬衫。

这三个商品都有互相相同的信息:库存量、价格和商品类型。

不同的信息则有:

  1. 图书:书名、作者和页数。
  2. 杯子:设计。
  3. 衬衫:设计、可选的颜色和尺寸。

如果我们不思考太多直接使用下面设计的结构体:

struct gift_list {
	// 公共属性
	int stock_number;
	double price;
	int item_type;
	// 图书
	char book_name[20];
	char author[30];
	int page_nums;
	// 杯子和衬衫共有
	char design[30];
	// 衬衫
	int colors;
	int sizes;
};

这样做实际上会浪费许多内存,比如对于图书而言,设计、颜色和尺寸并不会去用或者说并不重要,对于杯子和衬衫而言,书名、作者和页数更不可能用到。

如果只把公共属性摘出来放在结构体中,因为这是必须要有的。然后再把各个商品本身的属性放在联合体内,这样在一定程度上节省了内存开销。

struct gift_list {
	// 商品的公共属性
	int stock_number;
	double price;
	int item_type;

	union {
		struct {
			char book_name[20];
			char author[30];
			int page_nums;
		} book; // 图书

		struct {
			char design[30];
		} mug; // 杯子

		struct {
			char design[30];
			int colors;
			int sizes;
		} shirt; // 衬衫
	} item; // 商品
};

在联合体内,最大空间的毫无疑问是图书,存放图书数据的大小存放其它两种商品肯定是没问题的,在同一时间里不会浪费太多内存空间。

你可能感兴趣的:(C语言,c语言)