文章目录
- 一、联合体(Union)
- 1.1 什么是联合体?
- 1.2 联合体的特点
- 1.3 联合体与结构体的对比
- 1.4 联合体大小的计算规则
- 1.5 联合体的典型应用
- 应用1:节省内存
- 应用2:判断机器字节序
- 二、枚举(Enum)
- 2.1 什么是枚举?
- 2.2 枚举的优势(对比#define)
- 2.3 枚举的使用方法
一、联合体(Union)
1.1 什么是联合体?
联合体是一种特殊的自定义类型,它由多个不同类型的成员组成,但所有成员共用同一块内存空间。这意味着联合体的大小仅需满足最大成员的存储需求,相比结构体能显著节省内存。
声明方式与结构体类似,关键字为union:
// 联合体类型声明unionUn{charc;// 字符型成员inti;// 整型成员};// 联合体变量定义unionUn un;1.2 联合体的特点
- 内存共用:所有成员共享同一块内存,起始地址相同。
#include<stdio.h>unionUn{charc;inti;};intmain(){unionUn un;printf("&un = %p\n",&un);// 输出:001AF85Cprintf("&un.i = %p\n",&un.i);// 输出:001AF85Cprintf("&un.c = %p\n",&un.c);// 输出:001AF85Creturn0;}上述代码中,联合体变量un及其成员i、c的地址完全相同,证明它们共用内存。
- 成员值相互影响:修改一个成员的值会影响其他成员。
#include<stdio.h>unionUn{charc;inti;};intmain(){unionUn un;un.i=0x11223344;// 赋值整型成员un.c=0x55;// 修改字符型成员printf("%x\n",un.i);// 输出:11223355return0;}原理:int类型占4字节,char占1字节。un.c修改的是un.i的第一个字节(低地址位),导致un.i的原值0x11223344变为0x11223355。
1.3 联合体与结构体的对比
| 类型 | 内存布局特点 | 大小计算方式 |
|---|---|---|
| 结构体(struct) | 成员占用独立内存,按对齐规则排列 | 所有成员大小之和(含填充字节) |
| 联合体(union) | 成员共用一块内存 | 至少为最大成员大小(需满足对齐) |
示例对比:
- 结构体:成员独立占用内存
structS{charc;// 1字节inti;// 4字节(因对齐,c后填充3字节)};// 大小:1 + 3(填充) + 4 = 8字节- 联合体:成员共用内存
unionUn{charc;// 1字节inti;// 4字节};// 大小:4字节(取最大成员大小)1.4 联合体大小的计算规则
- 基础规则:联合体大小至少为最大成员的大小。
- 对齐规则:若最大成员大小不是“最大对齐数”的整数倍,需向上对齐到整数倍。
(对齐数:成员自身大小与默认对齐数的较小值,默认对齐数通常为4或8)
示例计算:
- 案例1:
char[5](大小5)与int(大小4)
unionUn1{charc[5];// 对齐数1,大小5inti;// 对齐数4,大小4};// 最大成员大小5,最大对齐数4。5不是4的倍数,向上对齐到8(4×2)。// sizeof(Un1) = 8- 案例2:
short[7](大小14)与int(大小4)
unionUn2{shortc[7];// 对齐数2,大小14inti;// 对齐数4,大小4};// 最大成员大小14,最大对齐数4。14不是4的倍数,向上对齐到16(4×4)。// sizeof(Un2) = 161.5 联合体的典型应用
应用1:节省内存
当数据包含“公共属性”和“互斥的特殊属性”时,用联合体存储特殊属性可减少内存浪费。
例如“礼品兑换单”设计:
- 优化前:结构体包含所有属性,浪费内存
structgift_list{// 公共属性intstock_number;// 库存量doubleprice;// 价格intitem_type;// 商品类型(1-图书,2-杯子,3-衬衫)// 特殊属性(互斥,仅一种生效)chartitle[20];// 书名(仅图书)charauthor[20];// 作者(仅图书)intnum_pages;// 页数(仅图书)chardesign[30];// 设计(仅杯子/衬衫)intcolors;// 颜色(仅衬衫)intsizes;// 尺寸(仅衬衫)};- 优化后:用联合体存储特殊属性
structgift_list{intstock_number;doubleprice;intitem_type;union{// 特殊属性共用内存struct{chartitle[20];charauthor[20];intnum_pages;}book;struct{chardesign[30];}mug;struct{chardesign[30];intcolors;intsizes;}shirt;}item;};优化后,特殊属性仅占用最大成员的内存(shirt结构体大小),避免了无效属性的内存浪费。
应用2:判断机器字节序
字节序是数据在内存中的存储顺序(大端/小端),联合体可简单判断:
// 返回1:小端(低地址存低位数据);返回0:大端(低地址存高位数据)intcheck_sys(){union{inti;// 4字节:0x00000001charc;// 1字节:取i的低地址位}un;un.i=1;returnun.c;// 小端:c=1;大端:c=0}二、枚举(Enum)
2.1 什么是枚举?
枚举用于定义有限个可能取值的集合,例如星期、性别、颜色等。它将离散值命名,增强代码可读性。
声明方式:
// 枚举类型声明(默认值从0开始递增)enumDay{Mon,// 0Tues,// 1Wed,// 2Thur,// 3Fri,// 4Sat,// 5Sun// 6};// 手动指定枚举值enumColor{RED=2,// 2GREEN=4,// 4BLUE=8// 8};enum Day、enum Color为枚举类型,Mon、RED等为枚举常量。
2.2 枚举的优势(对比#define)
| 优势 | 说明 |
|---|---|
| 增强可读性 | 用RED代替1,代码意图更清晰。 |
| 类型检查更严格 | 枚举变量只能接收枚举常量,#define定义的常量无类型限制。 |
| 便于调试 | 预处理阶段会删除#define符号,而枚举常量在调试时可见。 |
| 批量定义常量 | 一次声明多个相关常量,无需重复写#define。 |
| 遵循作用域规则 | 枚举声明在函数内时,仅在函数内有效,避免全局命名污染。 |
2.3 枚举的使用方法
- 定义枚举变量:
enumColor{RED,GREEN,BLUE};enumColorclr=GREEN;// 用枚举常量赋值- 赋值规则:
- C语言允许直接赋值整数(不推荐,破坏类型检查):
enumColorclr=2;// C中允许,C++中禁止- 建议始终使用枚举常量赋值,保证代码规范性。