当前位置:网站首页>C语言进阶 —— 枚举与联合
C语言进阶 —— 枚举与联合
2022-07-29 18:50:00 【Shark-s】
前言
今天我们会给大家介绍一下枚举和联合体这两个概念,这两者我们其实和结构体结合起来对比学习,三者之间都有其相似之处,当然也有不小的区别,我们今天将会从枚举和联合体的基本定义入手,剖析二者的使用和功能。
一、枚举
我们先讲枚举,从字面意义上来说,枚举的意思就是一一列举
即把所有有可能的值一一列举
比如说:一月份一共有31天,这是有限的,我们是可以一一列举的
又如:性别只有三种情况,男、女或者保密,我们也可以一一列举
等等…
诸如此类,我们都可以称其为列举
在这种情况下我们就可以使用枚举了
1.1 枚举类型的定义
先来看几个例子:
enum Day //星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex //性别
{
MALE,
FEMALE,
SECRET
};
以上定义的 enum Day,enum Sex都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫枚举常量 。
那如果现在我们想描述一下星期应该怎么用代码表达出来呢?我们可以这样做:
int main()
{
enum Day d = Fri;
return 0;
}
以此类推,其他的枚举类型也是如此
在这里可能有人会问了,既然大括号内的内容叫做枚举常量,那么枚举常量有没有值呢?
在这里我可以很明确的告诉大家,这些枚举常量都是有值的,大家可以尝试用printf函数将所有的枚举常量的值一一打印出来比对一下,
我们很容易就可以发现一个有趣的规律:我们枚举的可能取值都是从0开始的,依次往下递增1,当然这里的前提是默认情况下。
那么我们是否可以修改它们的值呢?比如我希望第一个枚举常量从1开始,其实这是很容易实现的,只需将"Mon"改为"Mon = 1"即可。
后面的枚举常量也和默认情况下一样依次递增1。
1.2 枚举的优点
为什么使用枚举?使用枚举的好处是什么?
首先我们知道,除了使用枚举,我们还可以使用#define定义常量,如:
#define Mon 1
#define Tues 2
//....
既然我们也可以使用define来定义一个常量,那相较于它而言,枚举的优势在哪里呢?
我们来看看枚举的优点:
增加代码的可读性和可维护性。
和#define定义的标识符比较枚举有类型检查,更加严谨。
防止了命名污染
便于调试
使用方便,一次可以定义多个常量
1.3 枚举的使用
看一个简单的例子大家就明白了:
enum Color //颜色
{
RED = 1,
GREEN = 2,
BLUE = 4,
};
enum Color clr = GREEN; //只能拿枚举常量个枚举变量赋值,才不会出现类型的差异
clr = 5;
二、联合体(共用体)
2.1联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列成员,特征是这些成员公用同一块空间(所以联合体也叫共用体)
比如:
union Un
{
int a;
char c;
};
那我们要怎么理解这个共用呢?我们可以进行下面这个操作:
int main
{
union Un u;
printf("%d\n", sizeof(u));
return 0;
}
按照我们惯有的思维习惯,一个整型+一个字符型至少也得占用5个字节
可是当我们执行程序后发现,只占用了4个字节,这就充分体现出了共用这一个特点。
我们可以再来看看二者的地址:
printf("%p\n", &u);
printf("%p\n", &(u.a));
printf("%p\n", &(u.b));
执行后我们可以发现,这三个地址是一模一样的,我们该如何解释呢?
其实解释起来非常简单:
我们先画出四个字节的空间,黄色部分就是a所占用的空间,而褐色部分就是b所占用的空间,他覆盖了a的一部分空间,但是二者是共存的,并不会有互斥的现象,这和共用体的名字也非常合拍。
2.2 联合的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的那位成员)。
我们在上文提到了共用这一概念。那有人就会提出问题,两者的地址是一样的,当你对其中一个变量进行改变时 ,另一个变量在内存中也会被改变,这就会产生问题了啊。
正是因为有这样的问题,所以我们要在实际使用时,我们在同一时间, 只使用其中一个变量,用了其中一个变量就不用另外的变量,这样就可以避免这个问题。
2.3 联合大小的计算
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
来看一个例子:
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
执行程序后我们发现,结果分别是8和16。这是为什么呢?
对于un1,当有数组的时候,最大对齐数为数组成员,un1中为char ,对齐数就是1,int 为4是un1中最大对齐数,故结果为8。
un2同理,short为2,数组共14,但是最大对齐数为4,整数倍故为16。
总结

边栏推荐
- R语言时间序列数据提取:使用xts包的last函数提取时间序列中最后面两周的数据(last 2 week)
- Typescript模块的导入导出与继承
- FPGA设计8位异步、同步二进制计数器
- swin-transformer初步理解
- 无人驾驶与人工驾驶的对比,人工驾驶的优缺点
- What should I do if the Win11 network is unstable?The solution to frequent disconnection of wifi connection in Win11
- 本科毕业六年,疫情期间备战一个月,四面阿里巴巴定级P7
- R语言使用zoo包表示时间序列数据(time series data)
- 2.5w字 + 36 张图爆肝操作系统面试题 学不吐你
- 制作文件上传进度条
猜你喜欢

Really touch the fish and lead the teacher: The programmer brother works 10 minutes a day with an annual salary of 570,000. I broke the defense...

leetcode:36. 有效的数独

OpenCV - 图像二值化处理 腐蚀膨胀 边缘检测 轮廓识别

centos8安装redis

Small application components

Neo4j Open Source NoSQL Database

500强企业如何提升研发效能?来看看行业专家怎么说

智能合约安全——重入漏洞

Small programs use npm packages

Android 面试黑洞——当我按下 Home 键再切回来,会发生什么?
随机推荐
大中型网站列表页翻页过多怎么优化?
Small programs use npm packages
函数的声明与作用域
R语言时间序列数据提取:使用head函数或者tail函数获取时间序列数据中最早或者最新的样本数据
支持向量机SVM
Setting right:0 after sticky positioning does not take effect
FPGA设计8位十进制计数器异步/同步模块以及m序列码产生器模块
MySQL筑基篇之增删改查
Neo4j Open Source NoSQL Database
一线大厂软件测试面试题及答案解析,2022最强版...
R语言时间序列数据提取:使用xts包的first函数提取时间序列中最前面两周的数据(first 2 week)
scroll bar style
Canal实现Mysql数据增量同步更新至Mysql/Redis
第01章 Linux下MySQL的安装与使用【1.MySQL架构篇】【MySQL高级】
EasyNVR更新版本至(V5.3.0)后页面不显示通道配置该如何解决?
Realize the size of an adjustable Switch Switch
swin-transformer初步理解
C# CLI(公共语言基础结构)
Custom Components -behaviors
R语言时间序列数据提取:使用xts包的first函数提取时间序列中最前面10天的数据(first 10 day)