自定义类型:联合和枚举

目录

引言

一.联合体

1.1 联合体的定义

1.2 联合体的声明 

1.3 联合体的特点

1.4 相同成员的结构体和联合体对比

1.5 联合体大小的计算

1.6 联合体的作用

1.7 联合体的小练习

二.枚举类型 

2.1 枚举的定义

2.2 枚举的声明

2.3 枚举的作用

2.4 枚举的使用示例

 后记


引言

之前我们学习了一种自定义类型:结构体,今天我们来学习另一种自定义类型:联合以及枚举。

我们先来学习联合体,那么什么是联合体呢?下面我们来具体学习。

一.联合体

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 枚举的声明

枚举类型的声明是指创建该类型变量的过程。一旦枚举类型被定义,就可以像使用其他基本数据类型(如intfloat等)一样声明该类型的变量。 

 

2.3 枚举的作用

1.增加代码的可读性和可维护性
2.和#define定义的标识符比较枚举有检查类型,更加严谨
3.防止了命名污染(封装)
4.便于调试
5.使用方便,一次可以定义多个常量

2.4 枚举的使用示例

 

那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。 

 后记

一个中秋又摆烂了,得振作起来好好学哦

喜欢这篇文章的小伙伴点点赞,点点关注哦,谢谢各位大佬们的支持!!!

共勉!!! 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值