目录
引言
之前我们学习了一种自定义类型:结构体,今天我们来学习另一种自定义类型:联合以及枚举。
我们先来学习联合体,那么什么是联合体呢?下面我们来具体学习。
一.联合体
1.1 联合体的定义
在C语言中,联合体(Union)是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,但在任何给定时间只能存储其中一个成员的值。这意味着联合体中的所有成员共享同一块内存空间,并且联合体的大小至少足够大,能够存储其最大成员。
1.2 联合体的声明
联合体的声明类似于结构体的声明,但使用union
关键字。在声明时,你需要指定联合体的名称以及它包含的各个成员的类型和名称。
这里,Un是一个联合体的名称,它包含了两个成员:一个int
类型的a,一个char类型的c。
1.3 联合体的特点
联合的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
下面我们通过分析两段代码来学习联合体的特点:
这段代码的结果是什么呢?
在这里我们发现:代码1输出的三个地址⼀模⼀样
下面我们来看代码2
这段代码的结果是什么呢?
代码2的输出,我们发现将i的第4个字节的内容修改为55了。 我们仔细分析就可以画出,un的内存布局图。
那么为什么上述两段代码会出现这样的结果呢?这就要说到联合体的特点了
联合体有如下特点:
内存共享:联合体的所有成员共享同一块内存空间。这意味着,当你给联合体的一个成员赋值时,其他成员的值会被覆盖,因为它们实际上指向的是同一块内存。
大小:联合体的大小至少足够大,能够存储其最大成员。但是,具体大小还可能受到编译器填充(padding)和对齐(alignment)要求的影响。
匿名联合体:C11标准引入了匿名联合体的概念,允许直接访问联合体的成员,而不需要通过联合体变量名。
用途:联合体常用于需要存储不同类型数据,但每次只使用其中一种类型的情况。例如,在处理网络通信协议时,不同的数据包可能具有不同的格式,但可以使用同一个联合体来接收这些数据,并根据需要解释它们。
学习了上述联合体的特点,我们再来看这两段代码就容易理解了。
在代码1中,由于联合体的所有成员共享同一块内存空间,所以代码1输出的三个地址⼀模⼀样。
在代码2中,由上述的图可知,当你给联合体的一个成员赋值时,其他成员的值会被覆盖,因为它们实际上指向的是同一块内存,则有了i的第4个字节的内容修改为55,从而改变了输出。
1.4 相同成员的结构体和联合体对比
我们再对比一下相同成员的结构体和联合体的内存布局情况。
结构体:
它的内存示意图如下:
联合体:
它的内存示意图如下:
1.5 联合体大小的计算
• 联合的大小至少是最大成员的大小。
• 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
下面我们来看一段代码:
那么为什么会出现这样的结果呢?
下面我们通过图像来分析:
注意:最大成员的判断是按照数据类型来判断的,char c[5]虽然是字符数组,占据5个字节,但它的类型依旧是char,比int小,则最大成员大小为4,最大对齐数是4,故占据内存数为它的整数倍8
Un2也是同理:short c[7]占据14个字节,但short所占字节为2,比int的所占字节4要小,所以最大成员大小为4 ,故占据内存数为它的整数倍16
1.6 联合体的作用
使用联合体是可以节省空间的
举例:
比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:
图书、杯子、衬衫。
每⼀种商品都有:
库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
杯子:设计
衬衫:设计、可选颜色、可选尺寸。
面对这种问题,可能小伙伴们就会直接用结构体来书写,我们也写出它的结构体形式:
上述的结构其实设计的很简单,用起来也方便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。比如: 商品是图书,就不需要design、colors、sizes。 所以我们就可以把公共属性单独写出来,剩余属于各种商品本⾝的属性使⽤联合体起来,这样就可以减少所需的内存空间,⼀定程度上节省了内存。
1.7 联合体的小练习
学习了联合体,下面我们来用联合体实现一个程序:判断当前机器是大端字节序还是小端字节序
二.枚举类型
枚举(Enumeration)是一种用户定义的类型,它允许程序员为整数常量指定名称,从而增加代码的可读性和可维护性。
2.1 枚举的定义
枚举类型的定义通常包含在一个enum
关键字后紧跟的标识符(即枚举类型的名称)中,然后是花括号{}
内的一组命名的整型常量(称为枚举成员或枚举器)。枚举成员之间通常用逗号分隔。
2.2 枚举的声明
枚举类型的声明是指创建该类型变量的过程。一旦枚举类型被定义,就可以像使用其他基本数据类型(如int
、float
等)一样声明该类型的变量。
2.3 枚举的作用
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较枚举有检查类型,更加严谨
3.防止了命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个常量
2.4 枚举的使用示例
那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。
后记
一个中秋又摆烂了,得振作起来好好学哦
喜欢这篇文章的小伙伴点点赞,点点关注哦,谢谢各位大佬们的支持!!!
共勉!!!
标签:自定义,代码,联合体,枚举,内存,类型,成员 From: https://blog.csdn.net/2401_85548793/article/details/142251856