15.9【保姆级教程】C语言联合(Union)从入门到精通:内存共享的终极玩法

张开发
2026/5/11 11:40:15 15 分钟阅读

分享文章

15.9【保姆级教程】C语言联合(Union)从入门到精通:内存共享的终极玩法
在C语言的复合数据类型中结构体(struct)是“各司其职”的代表而联合(union)则是“共享空间”的高手——它能让不同类型的数据共用同一块内存堪称处理混合类型数据的“神器”。本文将以「零基础能落地」为目标从联合的核心原理、基础用法、匿名联合C11特性到实战案例全方位拆解联合的使用技巧看完就能上手写代码彻底搞懂“内存共享”的底层逻辑一、先搞懂什么是联合(Union)1.1 联合的核心定义联合也译作“共用体”是C语言特有的复合数据类型它允许不同数据类型的变量共享同一块内存空间但同一时间只能有一个成员生效即只有最后赋值的成员值是有效的。1.2 联合 vs 结构体核心区别新手必看很多人会把联合和结构体搞混用一张表讲透本质区别特性结构体(struct)联合(union)内存分配各成员独立分配内存总大小各成员大小之和含内存对齐所有成员共享同一块内存总大小最大成员的大小含内存对齐数据存储各成员同时存在可独立读写同一时间仅一个成员有效赋值新成员会覆盖旧成员访问规则可同时操作不同成员读写一个成员会导致其他成员数据失效典型场景存储固定结构的多字段数据如员工信息存储无规律的混合类型数据如通用数组通俗比喻结构体像“一套带多个房间的房子”每个房间成员独立可同时放东西联合像“一个单间房子”只能放一种家具成员换家具必须先把原来的搬走。1.3 联合的适用场景联合的核心价值在于“灵活存储混合类型数据”典型应用场景处理无规律的混合类型数据如既存整数、又存浮点数、还存字符的通用数组硬件寄存器操作嵌入式开发中用不同类型解析同一段寄存器内存节省内存空间嵌入式/单片机等内存受限场景实现数据的“类型转换”通过共享内存解析二进制数据。二、基础篇手把手教你用联合创建联合的方式和结构体高度相似核心分为“定义模板”和“创建变量”两步新手优先掌握「带标记的分步定义」。2.1 联合的3种定义方式方式1带标记的分步定义推荐可复用这是最常用的方式先定义联合模板标记再基于模板创建变量#includestdio.h// 第一步定义联合模板标记为data_unionuniondata_union{intival;// 整型4字节floatfval;// 浮点型4字节charcval;// 字符型1字节};intmain(){// 第二步基于模板创建联合变量uniondata_union u1;// 空变量uniondata_union u2{.ival100};// 初始化整型成员C99及以上支持return0;}方式2一步定义无标记仅创建变量直接定义联合并创建变量无标记后续无法复用模板适合临时使用#includestdio.hintmain(){// 直接定义联合创建变量u3无标记union{intival;floatfval;charcval;}u3{.fval3.14f};// 初始化浮点型成员return0;}方式3typedef简化定义实战常用用typedef给联合起“别名”后续可直接用别名创建变量代码更简洁#includestdio.h// 用typedef定义联合并起别名DataUniontypedefunion{intival;floatfval;charcval;}DataUnion;intmain(){// 直接用别名创建变量DataUnion u4{.cvalA};// 初始化字符型成员return0;}2.2 验证联合的内存大小关键实验联合的总大小由最大成员的大小决定需满足系统内存对齐写一段代码验证#includestdio.h// 定义联合uniondata_union{intival;// 4字节floatfval;// 4字节charcval;// 1字节};// 定义结构体对比structdata_struct{intival;// 4字节floatfval;// 4字节charcval;// 1字节};intmain(){// 输出内存大小sizeof是获取类型/变量字节数的核心函数printf(联合的大小%zu 字节\n,sizeof(uniondata_union));// 输出4最大成员大小printf(结构体的大小%zu 字节\n,sizeof(structdata_struct));// 输出124413字节对齐return0;}运行结果联合的大小4 字节 结构体的大小12 字节✅ 结论联合仅占用最大成员的内存空间内存利用率远高于结构体2.3 联合的赋值与访问核心规则核心铁律联合同一时间只能有一个成员有效赋值新成员会覆盖旧成员的内存访问未生效的成员会得到“乱码”。完整示例代码#includestdio.h// 定义联合typedefunion{intival;floatfval;charcval;}DataUnion;intmain(){// 1. 初始化联合默认给第一个成员赋值或指定成员DataUnion u{.ival100};// 初始化整型成员此时ival生效printf(【初始化后】整型值%d\n,u.ival);// 有效输出100printf(【初始化后】浮点值乱码%f\n,u.fval);// 无效内存二进制解析为浮点数值随机// 2. 赋值浮点型成员覆盖原有内存fval生效u.fval3.14f;printf(\n【赋值浮点后】浮点值%.2f\n,u.fval);// 有效输出3.14printf(【赋值浮点后】整型值乱码%d\n,u.ival);// 无效浮点数二进制解析为整数值随机// 3. 赋值字符型成员再次覆盖内存cval生效u.cvalA;printf(\n【赋值字符后】字符值%c\n,u.cval);// 有效输出Aprintf(【赋值字符后】浮点值乱码%.2f\n,u.fval);// 无效字符二进制解析为浮点数值随机return0;}运行结果示例【初始化后】整型值100 【初始化后】浮点值乱码0.000000 【赋值浮点后】浮点值3.14 【赋值浮点后】整型值乱码1078523331 【赋值字符后】字符值A 【赋值字符后】浮点值乱码0.00关键提醒不要同时读写联合的不同成员否则会得到无意义的乱码建议给联合搭配一个“类型标记”如char type标记当前生效的成员类型后续实战会用到。三、进阶篇匿名联合C11新特性匿名联合是C11标准新增的特性核心是“无标记、无变量名”直接嵌套在结构体/其他作用域中访问成员时无需写联合名语法更简洁。3.1 匿名联合的定义与使用#includestdio.h// 结构体中嵌套匿名联合核心用法structmixed_data{chartype;// 类型标记i整型, f浮点, c字符// 匿名联合无标记成员直接属于外层结构体union{intival;floatfval;charcval;};};intmain(){structmixed_datamd;// 1. 存储整型标记为imd.typei;md.ival200;// 直接访问联合成员无需写联合名printf(类型%c值%d\n,md.type,md.ival);// 2. 存储浮点型标记为fmd.typef;md.fval6.66f;printf(类型%c值%.2f\n,md.type,md.fval);// 3. 存储字符型标记为cmd.typec;md.cvalB;printf(类型%c值%c\n,md.type,md.cval);return0;}运行结果类型i值200 类型f值6.66 类型c值B3.2 匿名联合的核心优势语法简洁无需为联合命名直接访问成员代码更精简内存高效联合成员仍共享内存外层结构体仅多一个“类型标记”的开销语义清晰结合“类型标记”使用能明确当前生效的成员避免访问乱码。3.3 注意事项匿名联合是C11特性编译时需确保编译器支持如GCC无需额外设置MSVC需开启C11编译选项匿名联合不能单独定义必须嵌套在结构体/函数等作用域中。四、实战篇联合的经典应用——混合类型数组联合的核心实战场景是创建「混合类型数据数组」数组元素大小一致联合大小每个元素可存储不同类型的数据完美解决“数据类型无规律”的问题。4.1 需求场景实现一个通用数组支持存储整型、浮点型、字符型数据并能正确遍历输出。4.2 完整实战代码#includestdio.h#defineARR_SIZE5// 数组最大长度// 步骤1定义带类型标记的联合核心typedefunion{intival;floatfval;charcval;}UnionData;// 步骤2定义数组元素类型标记 联合数据typedefstruct{chartype;// 类型标记iint, ffloat, ccharUnionData data;}ArrayElement;// 步骤3遍历输出数组根据类型标记解析值voidprint_mixed_array(ArrayElement*arr,intn){printf(\n 混合类型数组内容 \n);for(inti0;in;i){printf(第%d个元素,i1);switch(arr[i].type){casei:printf(整型值 %d\n,arr[i].data.ival);break;casef:printf(浮点值 %.2f\n,arr[i].data.fval);break;casec:printf(字符值 %c\n,arr[i].data.cval);break;default:printf(未知类型\n);}}}intmain(){// 初始化混合类型数组5个元素类型随机ArrayElement arr[ARR_SIZE]{{i,.data.ival10},{f,.data.fval2.5f},{c,.data.cvalX},{i,.data.ival100},{f,.data.fval9.99f}};// 输出数组内容print_mixed_array(arr,ARR_SIZE);return0;}运行结果 混合类型数组内容 第1个元素整型值 10 第2个元素浮点值 2.50 第3个元素字符值 X 第4个元素整型值 100 第5个元素浮点值 9.994.3 实战核心思路用UnionData存储不同类型的数据共享内存用type标记当前联合中生效的成员类型遍历数组时根据type选择对应的成员解析避免访问乱码。五、避坑指南使用联合的8个关键注意事项同一时间仅一个成员有效这是联合的核心规则违反必出乱码内存对齐问题联合的大小是最大成员的大小需满足系统内存对齐如包含double8字节和int4字节的联合大小为8字节初始化规则C89仅支持初始化第一个成员C99及以上支持指定成员初始化如.ival 100字符指针陷阱联合中避免使用char*存储的是地址而非字符串内容改用字符数组匿名联合兼容性确保编译器支持C11否则会编译报错跨平台字节序二进制数据跨平台如x86小端/ARM大端时联合解析可能出错需统一字节序不要返回局部联合函数中不要返回局部联合变量的指针函数结束后内存释放调试技巧用sizeof验证联合大小用type标记跟踪生效成员。六、总结联合的核心知识点核心本质联合是“内存共享容器”所有成员共用同一块内存总大小最大成员大小核心规则同一时间仅一个成员有效赋值新成员会覆盖旧成员核心用法基础用法定义联合模板→创建变量→赋值/访问搭配类型标记进阶用法匿名联合C11简化嵌套场景语法实战用法混合类型数组解决无规律数据存储问题核心场景混合类型数据存储、嵌入式寄存器操作、内存优化。掌握联合的使用你就解锁了C语言“灵活操作内存”的关键技能无论是常规开发还是嵌入式编程都能应对更多复杂场景 关注博主获取更多C语言进阶干货结构体/联合/文件操作/指针实战 评论区留言“联合实战”交流你遇到的问题或优化思路 点赞收藏巩固联合的核心知识点下次用到不迷路#C语言 #联合 #Union #匿名联合 #内存共享 #混合类型数据 #实战教程欢迎关注获取更多技术干货 C语言宝藏资源包免费送14 本 C 经典书 编译工具全家桶 高效编程技巧搭配 C 语言精选书籍、20 算法源码 项目规范还有 C51 单片机 400 例实战从零基础到嵌入式开发全覆盖学生党、职场人直接抄作业 关注文章末尾的博客同名公众号回复【C 语言】一键解锁全部资源手慢也有​

更多文章