枚举和联合体
枚举
枚举顾名思义就是一一列举。把可能的取值一一列举出来。
比如,现实生活中:
- 一周的星期一到星期日是有限的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。比如:
typedef enum Color
{
RED,
GREEN,
BLUE
}color_t;
int main()
{
color_t clr = RED;
printf("RED=%d\n", clr);
printf("GREEN=%d\n", GREEN);
printf("BLUE=%d\n", BLUE);
system("pause");
return 0;
}
// 结果:RED=0
// GREEN=1
// BLUE=2
当然在定义的时候也可以赋初值。比如:
enum Color{ RED=2, GREEN=10, BLUE };
int main()
{
printf("RED=%d\n", RED);
printf("GREEN=%d\n", GREEN);
printf("BLUE=%d\n", BLUE);
return 0;
}
//结果:RED=2
// GREEN=10
// BLUE=11
枚举的优点
- 增加代码的可读性和可维护性。
- 跟 #define 定义的标识符比较枚举有类型检查,更加严谨。
- 进行了封装,防止了命名污染。
- 便于调试。
- 使用方便,一次可以定义多个常量。
联合体
联合体的定义
联合体也是一种特殊的自定义类型。
这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块内存空间(所以联合体也叫共用体)。
比如:
//联合类型的声明
union Un
{
char c;
int i;
};
//联合变量的定义
union Un un;
//计算联合变量的大小
printf("%d\n", sizeof(un)); // 4
联合的特点
联合的成员共用同一块内存空间,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的那个成员)
union Un
{
char c;
int i;
};
int main()
{
union Un un;
//下面输出的结果是一样的吗?
printf("%x\n", &(un.i));
printf("%x\n", &(un.c));
//一样,即 &(un.i)=&(un.c)=&un
//因为它们共用同一块内存空间,取地址时,取得都是首元素的地址。
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i); // 0x11223355(小端情况下)
return 0;
}
联合体大小的计算
- 联合体的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
例1:
union Un1
{
char c[5]; //5
int i; //4
};
printf("%d\n", sizeof(union Un1)); // 8
解析:
第一步,联合体的大小至少是5;
第二步,因为5不是最大对齐数4的倍数,所以就要让它对齐到4的比5大的最小的倍数。即是8.
例2:
union Un2
{
short c[7]; // 2*7=14
int i; // 4
};
printf("%d\n", sizeof(union Un2)); // 16
解析:
第一步,联合体的大小至少是14;
第二步,因为14不是最大对齐数4的倍数,所以就要让它对齐到4的比14大的最小的倍数。即是16.
例3:联合体与结构体巧妙的结合
//将long类型的IP地址,转换成点分十进制的表示形式
union ip_addr
{
unsigned long addr;
struct
{
unsigned char c1;
unsigned char c2;
unsigned char c3;
unsigned char c4;
}ip;
};
int main()
{
union ip_addr my_ip;
my_ip.addr = 176238749;
printf("%d.%d.%d.%d\n", my_ip.ip.c4, my_ip.ip.c3, my_ip.ip.c2, my_ip.ip.c1);
system("pause");
return 0;
}
// 结果:10.129.48.157