C语言自定义类型:联合和枚举完全指南
联合(共用体)和枚举是C语言中两种重要的自定义类型。联合体所有成员共享同一块内存,而枚举用于定义一组命名的整数常量。本文将系统讲解联合体的声明、特点、大小计算,以及枚举的声明、优点和使用方法,并通过实例帮助读者灵活运用。
目录
一、联合体类型的声明
联合体(union)与结构体类似,由多个不同类型的成员组成,但所有成员共用同一块内存空间 ,因此联合体也叫共用体。编译器只为最大的成员分配足够的内存。
c
union Un {
char c;
int i;
};
int main() {
union Un u;
printf("%zu\n", sizeof(u)); // 输出4(int占4字节)
return 0;
}
二、联合体的特点
- 所有成员的地址相同,即它们从同一个内存位置开始存储。
- 修改一个成员会影响其他成员的值。
验证地址相同:
c
union Un { char c; int i; };
union Un u;
printf("%p\n", &u); // 联合体地址
printf("%p\n", &u.c); // 与上面相同
printf("%p\n", &u.i); // 与上面相同
修改成员相互影响:
c
u.i = 0x11223344;
u.c = 0x55;
printf("%x\n", u.i); // 输出0x11223355(低字节被修改)
在小端 机器上,u.c 修改了 u.i 的低地址字节(即最低有效字节)。这一特性可用于判断字节序(大小端):
c
int check_sys() {
union { int i; char c; } u;
u.i = 1;
return u.c; // 返回1为小端,0为大端
}
三、联合体大小的计算
联合体的大小至少是最大成员的大小,但需满足对齐要求 :总大小必须是所有成员对齐数的最大值的整数倍。
c
union Un1 {
char c[5]; // 5字节,对齐数为1
int i; // 4字节,对齐数为4
}; // 最大对齐数4,总大小须为4的倍数 → 8
union Un2 {
short c[7]; // 14字节,对齐数为2
int i; // 4字节,对齐数为4
}; // 最大对齐数4,总大小须为4的倍数 → 16
printf("%zu %zu\n", sizeof(union Un1), sizeof(union Un2)); // 8 16
实际应用:节省内存的礼品单设计
使用结构体时,所有属性都占用空间,造成浪费。利用联合体,不同商品共享特殊属性区域,可大幅节省内存:
c
struct gift_list {
int stock_number;
double price;
int item_type;
union {
struct { char title[20]; char author[20]; int num_pages; } book;
struct { char design[30]; } mug;
struct { char design[30]; int colors; int sizes; } shirt;
} item;
};
四、枚举类型的声明
枚举(enum)用于将可能的值一一列举,定义一组命名的整数常量。
c
enum Day { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
enum Sex { MALE, FEMALE, SECRET };
enum Color { RED, GREEN, BLUE };
- 默认情况下,枚举常量从
0开始,依次递增。 - 可显式指定初始值:
c
enum Color { RED = 2, GREEN = 4, BLUE = 8 };
五、枚举类型的优点
相比 #define 定义常量,枚举具有以下优势:
- 增强代码可读性和可维护性:含义明确的名称比数字更直观。
- 类型检查更严格:枚举变量只能接受枚举值(C中允许整数赋值,但C++禁止)。
- 便于调试 :枚举符号在调试器中可见,而
#define宏在预处理阶段被替换,难以追踪。 - 一次定义多个常量 ,无需重复使用
#define。 - 遵循作用域规则:枚举声明在函数内,则仅在该函数内有效。
六、枚举类型的使用
c
enum Color clr = GREEN; // 使用枚举常量赋值
// 在switch语句中非常清晰
switch (clr) {
case RED: printf("红色\n"); break;
case GREEN: printf("绿色\n"); break;
case BLUE: printf("蓝色\n"); break;
}
在C语言中,可以将整数值赋给枚举变量(虽然不推荐),但在C++中不允许,这体现了C++更强的类型安全。
总结:联合体通过共享内存节省空间,适合存储互斥的成员;其大小需满足对齐要求。利用联合体可以巧妙实现字节序判断。枚举定义命名的整数常量,比
#define更安全、可读、可调试,适合表示状态、选项等有限集合。掌握联合和枚举,能编写更高效、更清晰的代码。