枚举:顾名思义就是一一列举
比如在我们的日常生活中,一个星期有7天,一年有12个月等等都可以使用枚举来一一列举表示。
枚举类型的定义:
//例1
enum sex
{
male, //注意逗号
female,
secret //注意最后一个成员末尾没有逗号
}
//例2
enum Color
{
red, //注意逗号
green,
blue //注意最后一个成员末尾没有逗号
};
//这里的enum sex,enum Color都是枚举类型,
//{}中的内容是枚举类型的可能取值,也叫作枚举常量。
//这里的可能取值都是有一个确定的值的,默认为0,依次递增,但是可以更改。
//举例1说明:取值都是有一个确定的值的,默认为0,依次递增
#include<stdio.h>
enum color
{
RED,
GREEN,
BLUE,
BLACK,
GRAY,
WHITE
};
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
printf("%d\n",BLACK);
printf("%d\n",GRAY);
printf("%d\n",WHITE);
return 0;
}
//举例2说明:枚举常量的值可以更改
#include<stdio.h>
enum color
{
RED = 10, //赋初值为10
GREEN,
BLUE,
BLACK,
GRAY,
WHITE
};
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
printf("%d\n",BLACK);
printf("%d\n",GRAY);
printf("%d\n",WHITE);
return 0;
}
例1结果:
例2结果:
下面举例说明一下这里通过赋初值改变枚举常量的值其他两种情况,
//情况1
#include<stdio.h>
enum color
{
RED,
GREEN,
BLUE,
BLACK = 10,//赋初值为10
GRAY,
WHITE
};
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
printf("%d\n",BLACK);
printf("%d\n",GRAY);
printf("%d\n",WHITE);
return 0;
}
//通过结果发现值的变化是从赋初值的成员往后开始变化的(依次递增1)
//如果赋初值的位置不是从第一个成员开始的,那么第一个成员到赋初值的成员
//之间的成员(包括第一个成员,不包括被赋初值的成员)的值依旧是默认从0
//开始,往后依次递增1,直到遇到被赋初值的成员,值开始从初值开始往后递增
//情况2
#include<stdio.h>
enum color
{
RED = 22,
GREEN = 33,
BLUE = 44,
BLACK = 55,
GRAY = 66,
WHITE = 77
};
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
printf("%d\n",BLACK);
printf("%d\n",GRAY);
printf("%d\n",WHITE);
return 0;
}
//由结果可知我们可以给每一个枚举常量都附上一个初值
情况1结果为:
情况2结果为:
总结: 枚举常量就是整数
枚举的使用
enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr1 = GREEN;
//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
//假如我们使用枚举常量所代表的值赋值
enum Color clr2 = 2;
//虽然二者意义相同,但请试想一周之后,一年之后,或者别人看你的代码时,
//结果可想而知,你或者别人根本就不会明白你的这个数字是什么意思
//这就是所谓的魔鬼数字。
枚举的优点
我们可以使用#define定义常量,为什么非要使用枚举?
1. 增加代码的可读性和可维护性
2. 与#define定义的标识符比较,枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
联合(共用体)
联合体特点
1、联合里的所有成员共用同一块空间,所以联合也叫作共用体。
2、联合体的大小至少(要考虑内存对齐)是最大成员的大小。因为联合至少得有能力保存最大的那个成员
3、联合体变量的地址和联合体内的所有成员的地址在数值上是一样的
union un
{
int i;
char c;
}x;
int main()
{
printf("%lu\n",sizeof(x));//该联合体的大小
printf("%p\n",&x);//联合体的地址
printf("%p\n",&x.i);//联合体中的成员i的地址
printf("%p\n",&x.c);//联合体中的成员c的地址
}
根据结果可以发现:联合体的大小至少是最大成员的大小;联合体变量的地址和联合体内所有成员的地址在数值上是一样的。
结果为:
联合体内存对齐
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
举例说明:
//联合0的最大对齐数为4
union un0
{
char a[5];
int i;
}x0;
//联合1的最大对齐数为2
union un1
{
char a[5];
short i;
}x1;
//联合2的最大对齐数为1
union un2
{
char a[5];
char i;
}x2;
int main()
{
printf("%lu\n",sizeof(x0));//联合0的大小(8)
printf("%lu\n",sizeof(x1));//联合1的大小(6)
printf("%lu\n",sizeof(x2));//联合2的大小(5)
}
//解析:
//联合0至少为5个字节,但5不是最大对齐数4的倍数,
//因此联合0的大小需为4的倍数就是8,
//联合1至少为5个字节,但5不是最大对齐数2的倍数,
//因此联合0的大小需为2的倍数就是6,
//联合2至少为5个字节,并且5是最大对齐数1的倍数,
//因此联合0的大小就是5.
结果为: