枚举顾名思义就是一一列举。
把可能的取值一一列举。
比如我们现实生活中:
一周的星期一到星期日是有限的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,当然在定义的时候也可以赋初值
(默认是从0开始的)
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
int main()
{
enum Sex sex;
//验证默认是从0开始的
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
return 0;
}
运行结果:
*****
0
1
2
*****
(赋值开头)
#include
enum Sex//性别
{
MALE = 1,
FEMALE,
SECRET
};
int main()
{
enum Sex sex;
//开头赋值的情况
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
return 0;
}
运行结果:
*****
1
2
3
*****
(中间赋值)
#include
enum Sex//性别
{
MALE ,
FEMALE = 0,
SECRET
};
int main()
{
enum Sex sex;
//中间赋值的情况
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
return 0;
}
运行结果:
*****
0
0
1
*****
总结:
- 枚举类型和结构体类型很相似,只过是结构体内部是成员,枚举内部是枚举常量(该类型可能出现的情况)
- 枚举常量默认是从1依次往下增大的,但是我们也可以赋初值(初始化),但之后就不能改变
- .赋初值的位置不同,产生的结果也就不同;在开头赋初值,依次往下递增;在中间赋初值,开头是0,往下递增,赋初值的地方依次往下递增
其实,在我们不了解枚举类型的情况下,我们一般都是用#define 定义常量,那么枚举类型相比于它又有什么优点呢?
枚举的优点:
(便于调试)
#define MAX 100
//这种情况下,在调试的时候所有的MAX都消失,直接变成100
//且没有#define MAX 100这段代码,不方便调试
enum max
{
MAX=100,
};
//记住枚举是一种类型,在调试的过程中比不会消失,方便调试
(增加代码的可读性与可维护性)
//假如,我们在写一个菜单
//第一种方法:
#include
int main()
{
printf("**************1.add 2.sub************\n");
printf("**************3.mul 4.div************\n");
printf("**************** 0.exit **************\n");
int input = 0;
scanf("%d", &input);
switch (input)
{
case 1;
break;
case 2;
break;
case 3;
break;
case 4;
break;
case 0;
break;
}
//这种情况下,我们会忘记每个数字代表的操作是什么
}
//第二种方法:
#include
int main()
{
printf("**************1.add 2.sub************\n");
printf("**************3.mul 4.div************\n");
printf("**************** 0.exit **************\n");
int input = 0;
scanf("%d", &input);
enum Option
{
exit,
add,
sub,
mul,
dix
};
switch (input)
{
case add;
break;
case sub;
break;
case mul;
break;
case div;
break;
case exit;
break;
}
//这种情况下,进行的操作和上面的是一样的效果
//但更清楚明了每一步要进行的操作是什么
}
只能拿枚举常量给枚举变量赋值,才不会出现类型的差异
#include
enum color
{
green = 1,
red = 5,
yellow = 4,
blue
};
int main()
{
enum color col = blue;
col = 5; //ok???
//虽然blue 和 5 的值是一样的
//但是,第一种情况下直接让col 是blue的值
//而第二种情况下,red跟blue都是5,会产生歧义,而且会产生类型上的差异
return 0;
}
- 联合也是一种特殊的自定义类型
- 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)
- 联合的关键字是union
#include
//联合的声明
union UN
{
int a;
char b;
};
int main()
{
//联合变量的定义
union UN un;
//联合变量大小的计算
printf("%d\n", sizeof(un));
return 0;
}
//运行结果:
*****
4
*****
在这里,我们不禁有一个疑问:
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
#include
union UN
{
int a;
char b;
};
int main()
{
union UN un;
printf("%p\n", &un);
printf("%p\n", &(un.a));
printf("%p\n", &(un.b));
return 0;
}
运行结果:
*****
012FFC94
012FFC94
012FFC94
*****
从这个例子说明,联合的每次只能单独出现一个出现一个变量,不然的话,进行不同的操作会导致内存紊乱
那看到这里,不得不提一下联合的一个巧妙用法 ----- 判断当前机器的大小端:
//判断当前机器的大小端
#include
union Clc
{
char a;
int b;
};
int main()
{
union Clc clc;
clc.b = 1;
if (clc.a == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
#include
union UN1
{
short arr[5];
int b;
};
union UN2
{
char arr[6];
int b;
};
int main()
{
printf("%d\n", sizeof(union UN1));
printf("%d\n", sizeof(union UN2));
return 0;
}
//运行结果:
*****
12
8
*****
自定义类型的总结:
- 结构体的大小存在对其行为
- 位段的大小不存在对齐行为
- 枚举的大小就是整形变量的大小,4个字节
- 联合的大小存在对其行为