C语言自定义类型:联合体与枚举
✅《C语言自定义类型:联合体与枚举》
本文基于 C 语言联合体(union)与枚举(enum)两个核心的自定义类型,通过图示、实例、底层解释进行系统讲解,适合初学者、进阶者与实战开发者阅读。
📚 目录
-
一、联合体(Union)
- 1.1 联合体的声明
- 1.2 联合体的底层特点(核心)
- 1.3 联合体覆盖示意图(关键)
- 1.4 结构体 vs 联合体:内存对比图
- 1.5 联合体大小计算规则(含对齐示意图)
- 1.6 使用联合体节省空间(实战例子)
- 1.7 练习:判断大小端
-
二、枚举类型(Enum)
- 2.1 枚举声明与默认值规则
- 2.2 枚举的优点(强烈推荐的原因)
- 2.3 枚举的底层值映射图
- 2.4 枚举变量的使用与注意事项
-
三、联合体 + 枚举:工程开发中的组合模式
-
四、强化练习(附答案)
-
五、总结
一、联合体(union)
联合体(Union)与结构体类似,也由多个不同类型的成员组成,但有本质区别:
❗联合体的所有成员共享同一块内存,因此只能同时保存其中一个成员的值。
1.1 联合体的声明
union Un {char c;int i;
};
定义变量:
union Un un;
大小:
printf("%d\n", sizeof(un));
输出通常为 4,因为最大成员 int 占 4 字节。
1.2 联合体的底层特点(核心)
联合体的三个核心点:
✅ 所有成员从地址上完全重叠
✅ 大小至少等于最大成员
✅ 对一个成员赋值会影响其他成员
验证地址:
printf("%p\n", &(un.c));
printf("%p\n", &(un.i));
printf("%p\n", &un);
三个地址一致,这说明:
c 和 i 完全重叠,共用同一块内存。
1.3 联合体覆盖示意图(关键)
下面是联合体写入两个成员时的行为示意图:
假设:
union Un {char c; // 1 字节int i; // 4 字节
};
写入 int:
un.i = 0x11223344;内存(小端机示意):
┌──┬──┬──┬──┐
│44│33│22│11│
└──┴──┴──┴──┘↑c(i)也使用这些字节
再写入 char:
un.c = 0xAA;
结果:
┌──┬──┬──┬──┐
│AA│33│22│11│
└──┴──┴──┴──┘
这个覆盖说明:
写入最小的成员会覆盖最大成员的低地址部分。
1.4 结构体 vs 联合体:内存对比图
结构体(struct)内存布局:
struct S {char c; //1 字节int i; //4 字节(对齐到4)
};内存:
┌────┬──────┬───────────┐
│ c │ pad │ i(4字节) │
└────┴──────┴───────────┘
联合体(union)内存布局:
union U {char c; //1 字节int i; //4 字节
};内存:
┌────────────┐
│ 共享的 4 字节 │
└────────────┘
总结:
| 类型 | 各成员是否独立占用空间 | 大小 |
|---|---|---|
| struct | ✅ 是 | 累加 + 对齐 |
| union | ❌ 否(共享) | 最大成员大小 |
1.5 联合体大小计算规则(含对齐示意图)
规则:
- 大小 >= 最大成员大小
- 大小必须对齐到最大对齐数的整数倍
例 1:
union U1 {char c[5]; //5 字节int i; //4 字节
};
最大成员 = c[5]
最大对齐 = int 的 4 字节
所以 U1 大小对齐到 8:
sizeof(U1) = 8
示意图:
c[5] ----> 5 字节
对齐到 4 字节倍数 → 8
1.6 使用联合体节省空间(实战例子)
文档例子使用“礼品兑换单”解释联合体节省空间的作用。
不使用联合体(浪费空间)
struct gift {int stock;double price;int type;char title[20];char author[20];int pages;char design[30];int colors;int sizes;
};
无论是哪种商品,都包含所有字段,非常浪费。
使用联合体(节省空间 ✅)
struct gift {int stock;double price;int type;union {struct { char title[20]; char author[20]; int pages; } book;struct { char design[30]; } mug;struct { char design[30]; int colors; int sizes; } shirt;} item;
};
图示:
┌─────────────┐
│ 公共属性 │
├─────────────┤
│ union(共享) │← 根据类型使用不同数据
└─────────────┘
1.7 练习:判断大小端
int check_sys() {union {int i;char c;} un;un.i = 1;return un.c; //1小端 0大端
}
利用联合体共享内存的特性,巧妙判断字节序。
二、枚举类型(enum)
枚举用于将一组离散、有限的值定义为常量。
2.1 枚举声明与默认值规则
示例:
enum Day {Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
默认从 0 递增:
Mon=0, Tues=1, … Sun=6
也可以手动赋值:
enum Color {RED = 2,GREEN = 4,BLUE = 8
};
2.2 使用枚举的优点(强烈推荐的原因)
| 特性 | #define | enum |
|---|---|---|
| 是否有类型检查 | ❌ 无 | ✅ 有 |
| 可读性 | 一般 | ✅ 高 |
| 调试时是否有符号 | ❌ 无 | ✅ 有 |
| 可否局部定义 | ❌ 否 | ✅ 是 |
总结:
✅ 枚举比 #define 更安全、更清晰、更专业。
2.3 枚举的底层值映射图
enum Color { RED=1, GREEN=2, BLUE=4 };对应映射关系:RED → 1
GREEN → 2
BLUE → 4
本质上:
枚举常量是整数常量(int 类型)。
2.4 枚举变量的使用与注意事项
enum Color clr = GREEN;
C 允许这样:
clr = 100; //合法
但 C++ 不允许(更严格的类型检查)。
三、联合体 + 枚举:工程开发中的组合模式
在实际工程(网络协议、变长数据结构、事件系统)中常出现:
✅ 用枚举表示类型
✅ 用联合体存储不同类型的数据
示例:
enum Type { BOOK, MUG, SHIRT };struct Gift {int stock;double price;enum Type t;union {struct { char title[20]; char author[20]; int pages; } book;struct { char design[30]; } mug;struct { char design[30]; int colors; int sizes; } shirt;} item;
};
这是 C 风格多态的经典写法。
四、强化练习(附答案)
✅ 练习 1
下面联合体大小是多少?
union U {char c[3];double d;
};
最大成员是 double = 8
对齐 8
所以:
✅ sizeof(U) = 8
✅ 练习 2
以下枚举值是多少?
enum A {X=3, Y, Z=10, W};
序号:
X=3
Y=4
Z=10
W=11
✅ 练习 3
判断输出:
union U {int i;char c;
};union U u;
u.i = 0x88776655;
printf("%x\n", u.c);
在小端机上结果:
✅ 55
五、总结
本文系统介绍了:
✅ 联合体(union)
- 所有成员共享内存
- 大小由最大成员和对齐决定
- 可用于节省空间
- 可用于大小端判断
- 常与枚举一起用于表达多种数据类型
✅ 枚举(enum)
- 可读性提升
- 具备类型检查
- 可调试性强
- 常用于状态、类别表示
结构体、联合体、枚举构成了 C 语言自定义类型的全部核心内容,是写出高质量 C 程序的基础。
