目录
[1.1 联合体的声明](#1.1 联合体的声明)
[1.2 联合体的核心特点:内存共享](#1.2 联合体的核心特点:内存共享)
[1.3 联合体大小的计算](#1.3 联合体大小的计算)
[1.4 联合体的实际应用](#1.4 联合体的实际应用)
[2.1 枚举类型的声明](#2.1 枚举类型的声明)
[2.2 枚举的核心优点](#2.2 枚举的核心优点)
前言:
在C语言的自定义类型中,联合体(Union) 和 枚举(Enum) 是两种灵活且实用的工具,它们既能优化内存使用,也能让代码更具可读性。下面我们逐一解析这两种类型的核心知识
一、联合体(Union):共享内存的"多面手"
1.1 联合体的声明
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同⼀块内存空间。所以联合体也叫:共用体。
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。
// 联合体的声明
union MyUnion {
char c; // 成员1:字符型
int i; // 成员2:整型
float f; // 成员3:浮点型
};
-
关键字是 union ,后接联合体名(如 MyUnion ),大括号内是成员列表。
-
定义变量时,可直接在声明后加变量名: union MyUnion u1; ,也可通过 typedef 简化:
typedef union MyUnion {
char c;
int i;
} MyUnion;
MyUnion u2; // 直接用MyUnion定义变量
1.2 联合体的核心特点:内存共享
与结构体(成员各自占用独立内存)不同,联合体的所有成员共享同一块内存空间,这是它最关键的特性:
-
同一时间,只能使用其中一个成员(若修改一个成员,其他成员的值会被覆盖)。
-
联合体的内存大小,由最大的成员大小决定(同时需满足内存对齐规则,见下文"大小计算")。
//代码1
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
// 下⾯输出的结果是⼀样的吗?
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
printf("%p\n", &un);
return 0;
}
输出结果:
001AF85C
001AF85C
001AF85C
//代码2
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}
输出结果:
11223355
代码1输出的三个地址⼀模⼀样,代码2的输出,我们发现将i的第4个字节的内容修改为55了。 我们仔细分析就可以画出,un的内存布局图。

1.3 联合体大小的计算
联合体的大小需满足两个规则:
-
至少容纳最大的成员:大小 ≥ 最大成员的字节数;
-
满足内存对齐:大小是"联合体中最大基本类型成员的对齐数"的整数倍。
union SizeDemo {
char arr[5]; // 大小5字节(基本类型是char,对齐数1)
int num; // 大小4字节(基本类型是int,对齐数4)
};
-
最大成员是 arr[5] (5字节);
-
最大基本类型对齐数是 int 的4字节;
-
因此联合体大小需是4的整数倍,且≥5 → 最终大小是8字节。
1.4 联合体的实际应用
联合体的核心价值是节省内存,常见场景:
-
存储不同类型但互斥的数据:比如一个变量"要么是字符,要么是整数",用联合体可避免额外内存开销;
-
类型转换(谨慎使用):利用内存共享特性,可实现不同类型的"强制转换"(但需注意平台的字节序):
union Convert {
int i;
char c[4];
};
union Convert u;
u.i = 0x12345678;
// 在小端序系统中,c[0]是0x78,c[1]是0x56,以此类推
二、枚举(Enum):给常量起"名字"
2.1 枚举类型的声明
枚举顾名思义就是⼀⼀列举。把可能的取值⼀⼀列举。
比如我们现实生活中:
⼀周的星期⼀到星期日是有限的7天,可以⼀⼀列举 性别有:男、女、保密,也可以⼀⼀列举
月份有12个有月,也可以⼀⼀列举 三原色,也是可以意义列举
这些数据的表⽰就可以使⽤枚举了
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
}
枚举是一种将一组常量命名的自定义类型,关键字是 enum ,用于替代无意义的数字常量
// 枚举的声明:表示"星期"的常量
enum Week {
Mon, // 默认值0
Tue, // 默认值1
Wed, // 默认值2
Thu, // 默认值3
Fri, // 默认值4
Sat, // 默认值5
Sun // 默认值6
};
-
大括号内是"枚举常量"(如 Mon 、 Tue ),默认从 0 开始依次递增;
-
也可手动指定枚举常量的值:
enum Week {
Mon = 1, // Mon=1
Tue, // Tue=2(自动递增)
Wed = 5, // Wed=5
Thu // Thu=6(自动递增)
};
2.2 枚举的核心优点
为什么使用枚举?
我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:
-
增加代码的可读性和可维护性
-
和#define定义的标识符比较枚举有类型检查,更加严谨。
-
便于调试,预处理阶段会删除 #define 定义的符号
-
使用方便,⼀次可以定义多个常量
-
枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用
-
简化维护:若需修改常量值,只需改枚举声明,无需逐个修改代码中的数字。
2.3枚举的实际使用
定义枚举变量后,可直接赋值枚举常量:
enum Week today;
today = Wed; // 合法:赋值枚举常量
// today = 10; // 不推荐:部分编译器会警告(类型不匹配)
也可通过 typedef 简化类型名:
typedef enum Week {
Mon, Tue, Wed
} Week;
Week tomorrow = Tue;
三、联合体与结构体的对比
为了更清晰区分,我们用表格对比联合体和结构体:
特性 联合体(Union) 结构体(Struct)
内存分配 所有成员共享同一块内存 每个成员占用独立内存,总大小是成员之和(+对齐)
成员使用 同一时间只能用一个成员 可同时使用所有成员
大小计算 由最大成员决定(+对齐) 成员大小之和(+对齐)
典型场景 互斥数据的存储、节省内存 不同属性的组合存储(如"学生"的姓名、年龄)
总结
联合体和枚举是C语言中"轻量级"的自定义类型:
-
联合体通过内存共享实现了内存优化,适合存储互斥的数据;
-
枚举通过给常量命名提升了代码的可读性与可维护性。
合理使用这两种类型,能让C语言代码更高效、更易读。