C语言进阶 —— 枚举与联合
前言
今天我们会给大家介绍一下枚举和联合体这两个概念,这两者我们其实和结构体结合起来对比学习,三者之间都有其相似之处,当然也有不小的区别,我们今天将会从枚举和联合体的基本定义入手,剖析二者的使用和功能。
一、枚举
我们先讲枚举,从字面意义上来说,枚举的意思就是一一列举
即把所有有可能的值一一列举
比如说:一月份一共有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。