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,这次的知识分享就到这里了,我们下次再见!

相关推荐
屁股割了还要学13 分钟前
【数据结构入门】时间、空间复杂度的计算
c语言·开发语言·数据结构·c++·算法
倒悬于世20 分钟前
ThreadLocal详解
java·开发语言·jvm
啃火龙果的兔子1 小时前
快速搭建Java服务指南
java·开发语言
未来之窗软件服务2 小时前
智慧收银系统开发进销存库存统计,便利店、水果店、建材与家居行业的库存汇总管理—仙盟创梦IDE
java·开发语言·ide·进销存·仙盟创梦ide·东方仙盟·收银台
pusue_the_sun2 小时前
从零开始搞定类和对象(上)
开发语言·c++
归云鹤2 小时前
QT信号和槽怎么传输自己定义的数据结构
开发语言·数据结构·qt
ytttr8732 小时前
MATLAB 实现 SRCNN 图像超分辨率重建
开发语言·matlab·超分辨率重建
饭碗的彼岸one2 小时前
重生之我在10天内卷赢C++ - DAY 1
linux·开发语言·c++·经验分享·笔记·学习方法
DIY机器人工房2 小时前
【科普】在STM32中有哪些定时器?
c语言·嵌入式·定时器·diy机器人工房
项目申报小狂人2 小时前
2025年1中科院1区顶刊SCI-投影迭代优化算法Projection Iterative Methods-附完整Matlab免费代码
开发语言·算法·matlab