【C语言】自定义数据类型:联合体和枚举

news/2025/3/26 5:35:58/

一、联合体(共用体)

和结构体一样,联合体也是由一个或者多个成员组成,这些成员可以是不同的类型。、

联合体和结构体的不同的就是,其所有成员共用一块内存空间,所以联合体也称为共用体,那么因为其是所有成员共用一块内存空间,所以其空间大小应该是最大的成员,而且当我们对其中一个成员赋值的时候,其他成员的值也会发生变化。

下面我们开始对联合体进行学习。

1、联合体的声明

联合体的声明和结构体的声明是类似的,结构体声明的时候是使用关键字struct,而联合体的声明则是使用union关键字。

其声明如下:

其变量创建的方式和结构体也是类似的,其变量的数据类型就是其关键字+名字。

如下:

2、联合体的特点 

联合体的成员都是使用同一块内存空间的,那么一个联合体变量的大小,至少也是其最大成员的大小。

运行结果:

可以看到上面代码中,联合体的成员的地址都是一样的,而且 联合体自己和成员的地址也是一样的,那么可以说明其是使用的一块空间。

下面我们再看如果对一个成员进行修改会不会影响另外一个成员。

代码如下:

我们试着分析上面的代码,首先我们对这个联合体变量a进行初始化0,然后我们对这个变量的成员i进行赋值,对其赋了一个16进制的11223344,然后将16进制数55赋值给成员a, 那么如果两个成员使用的是同一块空间,那么我们在对a进行赋值的时候,那么i应该会跟着发生改变。

那么在内存中,vs是小端字节序的存放,那么其在内存的存放是:44 33 22 11,然后再对a进行赋值,那么给它赋值的55就应该会将原来存放44的空间进行修改了。

下面我们看看运行结果:

可以看到其就是将44的位置的空间存放的内容修改了,这个结果进一步可以证明联合体的成员是共用的一个空间。

3、联合体大小的计算 

要计算其大小,那么我们就需要其在内存中是如何存储的。

其存储的规则如下:

1、联合体的大小至少是最大成员的大小,因为我们至少要保证其每个成员都可以存储。

2、当最大的成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

首先我们看第一个联合体Un1,先看第一个规则,其最大的成员是字符数字c其大小为5,那么其此时的空间大小至少为5,然后我们再看第二个规则,这个联合体的最大对齐数应该为4那么其最终的大小应该为4的倍数,那么此时这个联合体的大小应该为8。

那么同理,第二个联合体,其第一个短整型,那么其这个短整型数组的大小为14,然后其对齐数为2,然后第二个成员的对齐数为4,那么最终的这个联合体的大小应该为4的倍数,那么最终这个联合体的大小有关应该为16。

下面我们看看运行结果:

4、练习 

使用联合体,判断当前的机器是大端字节序还是小端字节序。

前面我们学习过大小端字节序,如果忘记了可以往前看。

前面我们是使用强制类型转换,将一个整型指针强制转换为字符指针,然后看其结果是不是为1,如果是1那么就是小端字节序,是0就是大端字节序。

下面我们看看在联合体中如何实现:

其实和上面的大差不差,上面的本质上是在同一块地址上进行操作,那么我们联合体刚刚好就契合这一点,那么我们可以创建一个联合体,其成员有一个整型,一个字符型。

然后我们先对整型成员进行赋值,那么此时其实也是对这个字符型成员也进行了赋值,那么我们此时判断这个字符型成员是否是1,如果是1那么就是小端,如果是0那么就是大端。

代码如下:

运行结果:

 

5、相同成员在结构体和联合体对比

下面我们看看结构体和联合体在内存上的区别:

下面我们画图来看看其在内存中的存放:

 

通过上面的图可以看到,联合体使用的空间是非常少的。

6、联合体的使用 

通过上面的学习我们知道了联合体是可以节省空间的,那么我们该在什么样的情况下使用联合体呢?

因为联合体中的成员,当对其中一个成员进行修改的时候,都可能会影响其他的成员。

那么我们可以想到,联合体中的成员,在实际上应该是有一些共同的内容的,比如说我们对一个物品进行描述,这个联合体中的成员只需要出现一次即可。

例如:

我们现在需要搞一个活动,然后需要上线一个礼品兑换单,礼品兑换单中有三个:图书,杯子,衬衫。

然后每一种商品的相关信息如下:

图书:书名、作者、页数。

杯子:设计。

衬衫:设计、颜色、尺寸。

那么我们可以直接使用结构体:

上面的话就是一窝蜂将这些属性直接创建在结构体中,这样会使得这个结构体占用的内存比较大,浪费空间。而且上面的内容中有的内容是不常用的。

比如说图书,其在颜色和尺寸的这些内容是不咋用的,那么其实我们可以将一些共同的属性单独写出来。

如下:
 

我们先将三者都有的库存量,定价,商品类型单独写出来,然后每种商品的特殊属性就使用联合体存放。

 然后我们在对某个礼品进行描述的时候,在同个时空的时候只会使用一个。

二、枚举

1、枚举类型的声明

枚举顾名思义就是⼀⼀列举。

把可能的取值⼀⼀列举。

⼀周的星期⼀到星期⽇是有限的7天,可以⼀⼀列举

性别有:男、⼥、保密,

也可以⼀⼀列举 ⽉份有12个⽉,

也可以⼀⼀列举

三原⾊,也是可以一一列举

所以枚举就是将这些可能的情况一一列举出来。

要注意的是枚举的关键字是enum。

下面我们将上面提到的使用枚举实现一下:

以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。

{}中的内容是枚举类型的可能取值,也叫 枚举常量 。

这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。

2、 枚举类型的优点

为什么使⽤枚举? 我们可以使⽤ #define 定义常量,为什么⾮要使⽤枚举?我们看看枚举的优点: 1. 增加代码的可读性和可维护性

2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。

 3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使⽤⽅便,⼀次可以定义多个常量

5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤ 

3、枚举的使用

我们先创建一个枚举,然再对其赋值。

上面就是我们枚举的使用了。 

 

 

 


http://www.ppmy.cn/news/1582651.html

相关文章

好用的Markdown阅读编辑器Typora破解记录

Typora破解 一、下载Typora二、安装Typora三、破解Typora 😀 记录一下Typora破解记录,怕不常用忘记咯,感觉自己现在的脑子就像我的肠子一样,刚装进去就么得了。。。😔 Typroa算是用起来很舒服的Markdown阅读器了吧&am…

Unity | 游戏数据配置

目录 一、ScriptableObject 1.创建ScriptableObject 2.创建asset资源 3.asset资源的读取与保存 二、Excel转JSON 1.Excel格式 2.导表工具 (1)处理A格式Excel (2)处理B格式Excel 三、解析Json文件 1.读取test.json文件 四、相关插件 在游戏开发中,策划…

如何借助es的snapshot跨集群迁移部分索引

1.创建源集群的快照仓库 使用fs方式,首先需要在所有节点挂载文件系统 然后在elasticsearch.yaml中新增配置path.repo 必须确保对应目录具备读写权限 path.repo: /mount/backups 修改配置重启完之后,开始创建快照仓库 PUT /_snapshot/my_repository…

数据结构与算法:宽度优先遍历

前言 进入图论部分难度明显提升了一大截,思路想不到一点…… 一、宽度优先遍历 1.内容 宽度优先遍历主要用于在图上求最短路。 (1)特点 宽度优先遍历的特点就是逐层扩展,最短路即层数 (2)使用条件 …

html5-Canvas弹跳小球项目开发总结

Canvas弹跳小球项目开发总结 这里写目录标题 Canvas弹跳小球项目开发总结项目介绍技术栈核心功能实现1. Canvas基础绘制2. 物理引擎模拟重力系统碰撞检测和弹跳 3. 拖拽交互实现拖拽检测拖拽状态管理速度计算 难点突破1. 平滑的物理效果2. 准确的拖拽体验3. 速度计算优化 优化思…

C++ 关系运算符重载和算术运算符重载的例子,运算符重载必须以operator开头

在C中,运算符重载允许为用户定义的类型(类或结构体)赋予某些内置运算符的功能。下面是一个关于关系运算符重载()和算术运算符重载()的简单例子。 示例:复数类的运算符重载 将创建一…

(每日一道算法题)翻转对

493. 翻转对 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums &#xff0c;如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。 你需要返回给定数组中的重要翻转对的数量。 示例 1: 输入: [1,3,2,3,1] 输出: 2示例 2: 输入: [2,4,…

高效事件驱动设计模式——Reactor 模式

Reactor 模式 1. 概述 Reactor 模式是一种用于处理并发事件的高效事件驱动设计模式。它广泛应用于高性能服务器、网络编程和异步 I/O 处理场景&#xff0c;例如 Nginx、Netty、libevent 等。Reactor 允许一个或多个I/O 线程&#xff08;Event Loop&#xff09;高效管理多个 I…