学习导航
写在前面
枚举
枚举类型的定义
枚举的使用
枚举的大小计算
枚举的优点
联合(共用体)
联合类型的定义
联合的内存分配
联合大小的计算
写在前面
我们知道的C语言中的自定义类型有:
结构 位段 枚举 联合
接下来,我们一起学习剩余两种自定义类型。
正文
枚举
枚举顾名思义就是一一列举。
把可能的取值一一列举。
比如我们现实生活中:
一周的星期一到星期日是有限的7天,可以一一列举。
性别有:男、女、保密,也可以一一列举。
月份有12个月,也可以一一列举
枚举类型的定义
enum Day//星期 { //枚举的可能取值 //枚举的可能取值都是常量,不可修改 Mon, //注意是逗号 Tues, Wed, Thur, Fri, Sat, Sun //结尾并没有; }; enum Sex//性别 { MALE, FEMALE, SECRET }; enum Color//颜色 { RED, GREEN, BLUE };
以上定义的 enum Day , enum Sex , enum Color 都是 枚举类型 。
{} 中的内容是枚举类型的可能取值,也叫 枚举常量 (常量不可修改但是可以赋初值) 。
这些可能取值都是有值的,默认从 0 开始,一次递增 1。
当然在定义的时候也可以赋初值。
例如:
enum Color//颜色 { RED = 1, GREEN = 2, BLUE = 4 };
或者
enum Color//颜色 { RED = 1, GREEN,//2 BLUE //3 };
某个值复制后,后面的值如果没有赋值默认增加1。
枚举的使用
定义一个枚举类型的变量:
#include<stdio.h> enum Color//颜色 { RED, GREEN, BLUE }; int main() { enum Color col = RED; printf("%d", col); //打印RED的值为0 return 0; }
既然RED的值为0,那我们能否将0赋值给col呢?
enum Color col = 0;//这样是否可行呢?
运行之后,我的编译器编译成功而且顺利运行。
但是并不代表这个语法在所有编译器下都是正确的。这取决与编译器对语法的容忍程度。
所以,只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
枚举的大小计算
之前计算结构体的大小时,结构体的成员都有明确的类型,结合内存对齐的知识就可以得到结构体的大小。而我们发现枚举里的成员都是常量没有类型,甚至貌似都没有一条完整的语句,那该如何计算呢?
我们不妨先用sizeof求出它的大小:
printf("%d", sizeof(enum Color));
运行之后,其结果是4。
解释:
回顾之前介绍枚举类型,枚举{}里面所列的是枚举的可能取值。
例如定义该枚举类型的变量:
enum Color col = BLUE;
col只能是{}中枚举的可能取值中的任意一个。
而之所以结果是4,是因为在我所使用的编译器下常量大小为4字节。
到这里,我们可能会好奇,这个玩意有什么用啊?
我们用#define不也能定义常量吗?
#define RED 0 #define GREEN 1 #define BLUE 2
那我们就谈一谈枚举的优点。
枚举的优点
我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和 #define 定义的标识符相比较,枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
此外,今后我们利用枚举来设置程序的菜单会显得更加美观。
联合(共用体)
联合与结构非常的相似,主要区别就在于联合这两个字。
联合的特征:联合体所包含的成员变量使用的是同一块空间。
联合类型的定义
直接看代码:
//联合类型的声明 union Un { char c; int i; }; //联合变量的定义 union Un un;
结果是 4。
如果它是结构体的话,那么结果应该是 8。
那我们就一起分析一下联合体的内存分配,看看差异从何而来。
联合的内存分配
有这样一个联合体类型:
union Un { char c; int i; double n; }; union Un un;//定义变量
我们采用暴力的方法,直接打印un每个成员的地址看看:
int main() { union Un un; printf("%p\n", &un); printf("%p\n", &un.c); printf("%p\n", &un.i); printf("%p\n", &un.n); return 0; }
运行之后
它们的起始地址都相同,也就说明他们所用的其实就是同一块空间 。
这也就意味着,我们要改变任何一个成员变量的值,都会改变另外两个成员变量的值。
例如:
现在un的i中存入0x11223344
int main() { union Un un; un.i = 0x11223344; return 0; }
然后改变un的c的值,看看内存如何变化:
un.c = 0x55;
果然如我们所想。
联合大小的计算
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
例如:
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));
结果如下:
本章完