C语言自定义数据类型详解(四)——联合体

好的,接下来我们来学习最后一个自定义数据类型------联合体。

一、什么是联合体:

联合体又叫共用体,用关键字union来进行定义。又因为所有的成员变量共用同一段内存空间(关于这一点,我们不久就会加以验证),所以它是一种比较特殊的自定义类型。

二、联合体的内存布局:

(1)验证联合体成员共用同一块空间:

我们前面已经提到了说联合体它的成员变量都是共用同一段内存空间的,我们可以通过下面这个代码对这一结论加以验证:

cpp 复制代码
#include<stdio.h>
union Uo
{
	int a;
	char i;
};
int main()
{
	union Uo u;
	printf("sizeof(u) == %zd\n", sizeof(u));
	printf("%p\n", &(u.a));
	printf("%p\n", &(u.i));
	return 0;
}

运行效果:

我们发现对于联合体u,它的大小是4Byte,且无论是针对它的成员变量a取地址,还是针对它的成员变量i取地址,它的结果都是一样的。

我们可以进一步做一些事情,我们修改变量a的值,然后来观察成员变量i是否会受影响。因此我们写出下面这个代码:

cpp 复制代码
#include<stdio.h>
union Uo
{
	int a;
	char i;
};
int main()
{
	union Uo u;
	u.a = 0x44332211;
    //%x是以十六进制打印整数:
	printf("0x%x\n", u.a);
	printf("0x%x\n", u.i);
	return 0;
}

运行结果(注意这里的结果你可能和我不一样,因为这和机器是小端字节序,还是大端字节序有关系。而博主现在是小端字节序的机器):

我们发现对联合体中某一个成员变量的值进行修改,也会影响到其他的成员变量。这里又进一步佐证了联合体的成员变量共用同一段内存空间这一事实。

综上,对于联合体变量union Uo u来说,它的内存布局是:


(2)联合体内存大小的计算:

有很多小伙伴在联合体这里会犯一个错误,认为联合体的大小就是最大成员变量的大小。但是其实不然,就比如说下面这个代码场景:

cpp 复制代码
#include<stdio.h>
union Uo
{
	int a;
	char i[5];
};
int main()
{
	union Uo u;
	printf("%zd\n", sizeof(u));
	return 0;
}

运行结果:

所以关于联合体的大小:我们认为联合体的大小至少是最大成员变量的大小。当最大成员变量的大小不是最大对齐数的整数倍时(关于对齐数可以看博主的前面的博客C语言自定义数据类型详解(二)------结构体类型(下)-CSDN博客)需要进行内存对齐。

三、联合体的应用场景:

我们试想这么一个场景:我们要求设计一些数据类型来存储图书布袋衬衫这三个商品的一些属性。那首先分析这三个商品,它们都有各自以下这些属性:

图书:库存量,价格,书名,作者;

布袋:库存量,价格,样式;

衬衫:库存量,价格,颜色,尺寸;

那据此,你可不可以设计下面这样的:

cpp 复制代码
struct book
{
	int _stock;  //库存
	float _price;//价格

	char _bookName[30];//书名
	char _writer[30];  //作者
};
struct bag
{
	int _stock;  //库存
	float _price;//价格

	char _style[30];//样式
};
struct shirt
{
	int _stock;  //库存
	float _price;//价格

	char color[15];//颜色
	size_t _size;  //尺寸
};

但是你有没有觉得这个设计比较冗余,因为库存量和价格都是这些商品共有的属性。这在C++,Java里面可以通过继承的方式来消除这种设计上的冗余,那C语言呢?OK,C语言可以借助联合体设计出下面这个结构体:

cpp 复制代码
#include<stdio.h>
#include<string.h>
struct commodity
{
	int _stock;  //库存
	float _price;//价格
	//这里面都是匿名结构体和匿名联合体哦!
	union
	{
		struct
		{
			char _bookName[30];//书名
			char _writer[30];  //作者
		} _book;
		struct
		{
			char _style[30];//样式
		} _bag;
		struct
		{
			char color[15];//颜色
			size_t _size;  //尺寸
		} _shirt;
	}_item;
};
int main()
{
	struct commodity com;
	//注意这里的_writer是char* const的指针(常量指针),所以不能写作com._item._book._writer = "MoYan";
	strcpy(com._item._book._writer, "MoYan");
	printf("The writer of the book is %s\n", com._item._book._writer);
	return 0;
}

OK,这次的知识分享就到这里了,我们下次再见!

相关推荐
风吹心凉17 分钟前
python3基础2026.7.22
开发语言·python
qq_4523962325 分钟前
第五篇:《接口与错误处理:Go 的哲学》
开发语言·后端·golang
Escalating_xu39 分钟前
C++可变参数模板与引用折叠精讲
开发语言·c++
wuyk55544 分钟前
59.嵌入式C语言高级宏定义实战:多行宏、字符串化与符号拼接
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·51单片机
云泽8081 小时前
Visual Studio 2026 新手保姆级教程:环境搭建、界面优化与编译器配置详解
开发语言·c++·c·开发工具·visual studio
2zcode2 小时前
基于MATLAB深度学习的乳腺钼靶影像乳腺癌智能诊断系统设计与实现
开发语言·深度学习·matlab·乳腺癌
MoonBit月兔2 小时前
错过大赛报名?MoonBit 开源大赛- 8 月黑客松正式开启
开发语言·ai-native·moonbit
weixin_538601972 小时前
智能体测开Day31
开发语言·python
geovindu2 小时前
java: Facade Pattern
java·开发语言·后端·外观模式·结构型模式
listening7772 小时前
HarmonyOS 6.1 元服务深度优化:从“秒开”到“常驻”的极致体验
java·开发语言·spring