该文章将详细介绍除结构体外的另外两种自定义类型--------枚举类型与联合类型。
1.枚举
枚举顾名思义就是------一一列举。
把所有可能的取值一一列举出来。
比如我们现实生活中:
星期一到星期天可以一一列举。
性别男女可以一一列举
月份12个月可以一一列举
这里就可以使用枚举了
1.1枚举类型的定义
enum Day//星期 { Mon, Tues, Wed, Thur, Fri, Sat, Sun }; enum Sex//性别 { MALE, FEMALE }; enum Color//颜色 { RED, GREEN, BLUE };
以上的 enum Day ,enum Sex,enum Color,都是枚举类型,它们是属于类型的,跟int ,char ,short,,等等是一样,只不过是自己定义的。{ }里面的是枚举类型的可能取值,叫做枚举常量
注意这些不是成员,是枚举类型的可能取值。
这些取值是都有值的,默认是从0开始,依次往下递增1,当然也可以在定义的时候给它进行初始化赋值。还有赋值后它就不能再改变了,因为它是‘ 常量 ’。
也可以在定义的时候初始化赋值。
enum Color//颜色 { RED=5, GREEN=8, BLUE=4 };
1.2枚举的优点
为什么要使用枚举?
我们可以用#define 定义常量,为什么要用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#define 定义的标识比较枚举定义的标识,枚举有类型检查,更加严谨
3. 防止了命名污染(封装)
4. 可以调试观察,便于调试
5. 使用方便,一次可以定义多个常量
1.3枚举的使用
enum Color//颜色 { RED=5, GREEN=8, BLUE=4 }; int main() { enum Color col = BLUE;//枚举变量col只能由枚举常量赋值,才不会出现类型差异 //如果这样写: RED=3;可以吗? return 0; }
2.联合(共用体)
2.1联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特点是这些成员公用同一块空间(所有联合也叫共用体)
比如:
//联合类型的声明 union UN { char c; int i; }; //联合类型的定义 union UN un; //联合成员的访问 (un.c) (un.i) //计算联合类型变量的大小 printf("%d\n", sizeof(un));
2.2联合的特点
1.联合的成员是共用同一块内存空间的,这样的一个联合变量的大小,至少是最大成员的大小(因为联合至少要有能力保存最大的成员)
2.联合的成员之间不能同时使用,使用其中一个,其他都不能使用。
union UN { char c;//1字节 int i;//4字节 }; union UN un; int main() { printf("%p\n", &un); printf("%p\n", &(un.c)); printf("%p\n", &(un.i)); return 0; } //上面输出结果相同吗?为什么呢?
说明char c,与int i,共用同一个地址,int i 4个字节中,c占用了一个1字节。
union Un { int i; char c; }; union Un un; //下面输出的结果是什么? un.i = 0x11223344; un.c = 0x55; printf("%x\n", un.i);
i,和c同时都使用了,都给各自赋值后,原来自己的值就会发现变化,因为它们共用同一块空间
2.3联合大小的计算
- 联合的大小至少是最大成员的大小
- 当最大成员大小不是最大对齐数的整数倍时候,就要对齐到最大对齐的整数倍。
例如:
union Un1 { char c[5]; int i; }un1; union Un2 { short c[7]; int i; }un2; int main() { //下面输出大小是多少? printf("%d\n", sizeof(un1)); printf("%d\n", sizeof(un2)); return 0; }
结果:
解析:
union Un1 { char c[5];//这里大小至少是最大成员5,但最大对齐是4,而5不是4的倍数,所有答案只能是8 int i; }un1; union Un2 { short c[7];//这里大小至少是最大成员14,而最大对齐数是4,而14不是4的倍数,所有答案只能是16了 int i; }un2;
还有一个与之相关的知识:利用联合的知识怎么证明当前机器是大段存储还是小段存储?
解1:
int check()//利用char类型指针解引用访问1个字节,如果数据在内存中倒着存,那访问1字节就能访问到1 { int i = 1; int* p = &i; return *((char*)p); } int main() { int ret=check(); if (ret == 1) { printf("小段\n"); } else printf("大段\n"); return 0; }
解2:
int check() { union Un { char c; int i; }un; un.i = 1; return un.c;//利用联合共用相同空间,给i赋值1,那c也存着i的数据,如果小段,那么c就是1 } int main() { int ret=check(); if (ret == 1) { printf("小段\n"); } else printf("大段\n"); return 0; }
结果: