C 语言枚举类型
实际问题中,有些变量的取值被限制在一定范围内。例如,一个星期内只有七天,一年
只有十二个月,一个班每周有六门课程等。
C 语言提供了一种枚举(Enum)类型,可以列出所有可能的取值。定义形式为:
enum 变量名{ 枚举值列表 };
这些值也称为枚举元素。注意最后的分号;不能少。
例如,列出一个星期有几天:
enum week{sun, mon, tue, wed, thu, fri, sat};
和结构体一样,枚举变量可以先定义后说明,也可以在定义的同时说明,例如:
enum week a, b, c;
或者:
enum week{sun, mon, tue, wed, thu, fri, sat} a, b, c;
枚举值为常量,不是变量,不能赋值。枚举值默认从 0 开始,逐个加 1。也就是说,上
面的代码定义了 7 个常量,分别为 sun、mon…sat,它们的值分别为 0、1…6。
【示例】枚举的使用。
#include <stdio.h>
int main(){
enum week{
sun, mon, tue, wed, thu, fri, sat
} a, b, c;
a = sun;
b = mon;
c = tue;
printf("%d, %d, %d\n",a,b,c);
return 0;
}
运行结果:
0, 1, 2
因为枚举值是常量,不能赋值,所以下面的写法是错误的:
sun = 5; mon = 2;
只能把枚举值赋予枚举变量,例如:
a = sun; b = sat;
同时,不建议把数值直接赋给枚举变量,例如:
a = 1; b = 6;
如果一定要使用数值,必须使用强制类型转换:
a = (enum week)1; b = (enum week)6;
因为已经使用了 sun、mon…sat 几个标识符,所以不能再使用它们来定义变量等,
例如:
int sun = 3; char mon;
都是错误的。
C 语言共用体(共同体)
共用体(共同体)的定义和结构体类似,不过结构体的各个成员都会分配相应的内存空
间,而共用体的所有成员共享一段内存,它们的起始地址一样,并且同一时刻只能使用其中
的一个成员变量。
共用体定义的一般格式为:
union 共用体名{
成员列表
};
共用体所占用的内存空间大小等于最长的成员所占用的字节数。共用体使用了覆盖技术,
几个成员变量相互覆盖,从而使几个不同变量共占同一段内存。这也就意味着,同一时刻只
能存放一个成员变量的值,只能有一个成员存在,不可能像结构体一样同时存放。如果对新
的成员变量赋值,就会把原来成员变量的值覆盖掉。
共用体 data 中,成员 i 所占用的空间最大,为 4 个字节,所以 data 类型的变量
(也就是 a、b、c)也占用 4 个字节的内存。请看下面的例子:
#include <stdio.h>
union{
int i;
char c;
}a;
int main(){
printf("Size of a: %d\n", sizeof(a));
a.c='A'; //此时共用体变量 4 个字节的取值情况为 0x00000041
printf("a.i = %d\n",a.i);
a.i=0x42; //0x42 为字母 B 的 ASCII 码
printf("a.c = %c\n",a.c);
return 0;
}
运行结果:
Size of a: 4
a.i = 65
a.c = B
两个不能:不能使用共用体变量,只能引用共用体变量中的成员。不能在定义共用体变 量时进行初始化。
C 语言类型定义符 typedef
C 语言不仅提供了丰富的数据类型,还允许用户定义自己的数据类型。
定义数据类型使用 typedef 关键字,一般形式为:
typedef 原类型名 新类型名;
例如:
typedef int INTEGER;
INTEGER a, b;
a = 1;
b = 2;
INTEGER a, b;等效于 int a, b;。
用 typedef 定义数组、指针、结构体等类型会带来很大的方便,不仅使程序书写简单
而且意义更加明确。例如:
typedef char NAME[20];
表示 NAME 是字符数组类型,长度为 20。然后可用 NAME 说明变量,如:
NAME a1, a2, s1, s2;
完全等效于:
char a1[20], a2[20], s1[20], s2[20];
又如:
typedef struct stu{
char name[20];
int age;
char sex;
} STU;
定义 STU 表示 stu 的结构体类型,然后可用 STU 来说明结构体变量:
STU body1,body2;
两点说明:
-
自定义数据类型必须以现有的数据类型为基础,可以认为是现有类型的“别名”,并
没有产生真正意义上的数据类型。为了“见名知意”,自定义数据类型一般大写,尽量使用
含义明确的标识符,例如:typedef (int*) PINT;
-
有时也可用宏定义来代替 typedef 的功能,但是宏定义是在预处理阶段完成的,
而 typedef 是在编译时完成的。