【结构体内功修炼】枚举和联合的奥秘(三)
1. 枚举
枚举顾名思义就是一一列举。
把可能的取值一一列举。
比如我们现实生活中:
1、一周的星期一到星期日是有限的 7 天,可以一一列举。
2、性别有:男、女、保密,也可以一一列举。
3、月份有 12 个月,也可以一一列举
这里就可以使用枚举了。
🍑 枚举类型的定义
📝 代码示例
以上定义的 enum Day
, enum Sex
, enum Color
都是枚举类型。
{ }
中的内容是枚举类型的可能取值,也叫 枚举常量 。
这些可能取值都是有值的,默认从 0 开始,一次递增 1,当然在定义的时候也可以赋初值。
📝 代码示例
🌟 运行结果
🍑 枚举的优点
为什么使用枚举?
我们可以使用 #define
定义常量,为什么非要使用枚举?
枚举的优点:
1、增加代码的可读性和可维护性;
2、和 #define
定义的标识符比较枚举有类型检查,更加严谨;
3、防止了命名污染(封装);
4、便于调试, #define
定义的常量是不能进行调试的
5、使用方便,一次可以定义多个常量
🍑 枚举的使用
📝 代码示例
2. 联合(共用体)
🍑 联合类型的定义
联合也是一种特殊的自定义类型;
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫 共用体)。
📝 代码示例
那么 u 占多少个字节呢?我们打印看一下👇
为什么是 4 呢?
别急,我们把 u 和它的成员地址全部打印出来看一看
我的天啊,它们三个的地址为啥都是一样的呢?
u、u.c、u.i 它们都指向第 1 个字节首地址;
c 占 1 个字节,i 占 4 个字节;
也就是 i 和 c 共用了第 1 个字节;
当我给 c 赋值的时候,我就把 i 的第一个字节给改变了;
当我给 i 赋值的时候,整个 c 也就被改了;
所以 联合体 比较特殊的地方在于:对于联合体的成员在同一时间只能用 1 个;
📝 代码示例
我们在内存中看一下调试结果👇
首先把第 1 个字节改为 w
然后又把整个 i 的内容改为 0x1223344
🍑 联合的特点
1、联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小;
2、因为联合至少得有能力保存最大的那个成员;
🍑 联合的应用
比如我现在要设计一个 学校用户系统 👇
1、学生:姓名、年龄、身份
2、老师:姓名、年龄、职称
📝 代码示例
身份 和 职称 都是相似的值,但它们只会用 1 个;
来看一道面试题:判断当前计算机的大小端存储
首先来看看什么是 大小端字节序
1、小端存储:假设 01 是低位字节的内容,00 是高位字节的内容,把低位字节的内容 01 放在低地址处,高位字节的内容 00 放在高地址处,这种存储方式叫 小端存储
1、大端存储:假设 01 是低位字节的内容,00 是高位字节的内容,把低位字节的内容 01 放在高地址处,高位字节的内容 00 放在低地址处,这种存储方式叫 大端存储
那么如何用代码来实现呢?
其实很简单,我们可以拿出第 1 个字节的内容,如果第 1 个字节的内容是 1,那么就是 小端存储;如果第 1 个字节的内容是 0,那么就是 大端存储;
📝 代码实现
🌟 运行结果
我们可以看到,a 的 int 类型,但我们在 check_sys()
实际使用的只有 1 个字节,那么对代码进行升级;
📝 代码升级
🌟 运行结果
这就是巧妙的运用到了 联合体,联合体 的成员会共用一块儿空间;
🍑 联合大小的计算
1、联合的大小至少是最大成员的大小。
2、当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
📝 代码示例一
成员 c 的类型是 char,所以它的对齐数是按照 char 来算的,也就是 1,而 VS 默认的对齐数是 8,取其较小值,那么它的对齐数就是 1;
成员 i 的类型是 int,所以它的对齐数是按照 int 来算的,也就是 4,而 VS 默认的对齐数是 8,取其较小值,那么它的对齐数就是 4;
成员 c 的对齐数是 1,成员 i 的对齐数是 4,那么最大的对齐数就是 4,而联合体的总大小必须是最大对齐数的整数倍;
又因为 c 是 char 类型的数组,有 5 个元素,所以有 5 个字节;i 是 int 类型,有 4 个字节;所以最大的就是 5 字节,但最大的对齐数是 4,不满足,所以就就是 8,也就是 4 的 2 倍。
🌟 运行结果
📝 代码示例二
c 是 short 类型,占 2 字节,有 7 个元素,所以占 14 字节;i 是 int 类型,占 4 字节;
那么取 14 就能存放下 Un2 的所有成员了,但是 14 是不是最大对齐数的整数倍呢?
成员 c 的类型是 short,所以它的对齐数是按照 short 来算的,也就是 2,而 VS 默认的对齐数是 8,取其较小值,那么它的对齐数就是 2;
成员 i 的类型是 int,所以它的对齐数是按照 int 来算的,也就是 4,而 VS 默认的对齐数是 8,取其较小值,那么它的对齐数就是 4;
成员 c 的对齐数是 2,成员 i 的对齐数是 4,那么最大的对齐数就是 4,而联合体的总大小必须是最大对齐数的整数倍,14 不是 4 的倍数,怎么办呢?
很简单,浪费掉 2 字节变成 16 就是 4 的倍数了。
🌟 运行结果
版权声明: 本文为 InfoQ 作者【Albert Edison】的原创文章。
原文链接:【http://xie.infoq.cn/article/0351fdd35a4e3547d6046bb10】。文章转载请联系作者。
评论