当前位置: 首页 > news >正文

C语言中的共用体(联合体)union

在定义结构体和共用体时,都是{}里面写成员,都是自定义复合类型,都可以嵌套、都可以做数组、指针。上节我们重点分析了结构体,本文将主要讲共用体。
一、定义
共用体是一种自定义数据类型,多个成员共享同一块空间。
同一时刻,只有一个成员是有效的;给一个成员赋值,会覆盖其他成员的值。
共用体占用的内存大小:等于它最大成员所占的字节数。

#include<stdio.h>#include<windows.h>#include<math.h>uniondata{inti;charc;floatf;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);uniondata d;printf("共用体data占:%d字节\n",sizeof(d));d.i=0x68;printf("i=%lx,c=%c\n",d.i,d.c);d.f=3.14f;//覆盖整个内存printf("f=%f,i=%lx\n",d.f,d.i);return0;}

运行结果:

赋值完d.f之后,再读d.i属于类型双关,C标准未定义这种行为,只是大部分编译器可以跑。
对于值的改变,我们通过下面这个例子可以清晰的看到,后面成员变量的赋值,直接把原来的值进行了部分覆盖:

#include<stdio.h>#include<windows.h>#include<math.h>uniondata{inta;shortb;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);uniondata s1;s1.a=0x01020304;s1.b=0x0102;printf("a=0x%X\n",s1.a);return0;}

运行结果:

二、使用场景
1、类型双关
把同一块内存,以不同类型视角解读。eg:把float二进制位当作整数查看

unionu{floatff;unsignedintii;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);unionu test;test.ff=1.0f;printf("ff=%f,ii=%lx\n",test.ff,test.ii);return0;}

运行结果:

2、节省空间
多个变量不会同时使用,放在union共用一块内存,减少内存占用。

structmag{inttype;uniondata{intival;floatfval;charcval;};};

例如:type=0,可以代表ival,type=1,代表fval;type=2代表cval
Msg结构体必须带type标记,工程上用union一定要加标记位,否则不知道哪个成员有效。
(3)硬件、网络协议、二进制报文解析
协议字段中,同一个位置,根据标志位不同代表不同含义,用union非常适合
(4)寄存器操作(嵌入式)
硬件寄存器,既可以整体读写,也可以按位/字节访问,使union变量互斥不同时使用,需要同一块内存做多种类型解释,内存紧张(嵌入式)
三、注意事项
1、同一时刻只有一个成员有效**(容易忽视,再重复)**
2、大小是最大成员大小,但是考虑内存对齐

unionu{chararr[5];inta;}

上面最大成员是5字节,但是对齐是按照int(4),sizeof(U)=8,不是5
3、不要混用指针
不要拿union不同成员的指针随意强制转化,容易对齐问题
4、联合体不能直接整体比较if(u1==u2),C语言不支持,需要自己逐个成员对比
5、大小端问题
CPU内部寄存器是按照bit取存储数据,但是CPU内部寄存器资源有限,需要把计算好的数据放到内存中,对于内存来说,它没有bit位的概念,是按照字节编号(地址)来寻址。把寄存器中数据存到内存,按照哪种顺序保存就是大小端的问题。
小端模式:数据的高位存到内存的高地址,数据的低位到内存的低地址(现阶段使用小端的比较多)。
大端模式:数据的高位存到内存的低地址,数据的低位存到内存的高地址。

用union拆分字节看底层二进制,程序受CPU大小端影响,跨平台代码要小心。
判断大小端的方法:

#include<stdio.h>#include<windows.h>#include<math.h>unionEndianCheck{unsignedintval;unsignedcharbytes[4];};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);unionEndianCheck test;test.val=0x01020304;printf("val=0x%08X\n",test.val);printf("bytes[0]=0x%02x bytes[1]=0x%02x bytes[2]=0x%02x bytes[3]=0x%02x\n",test.bytes[0],test.bytes[1],test.bytes[2],test.bytes[3]);//对于寄存器,右边是低位;对内存,左边是低地址。if(test.bytes[0]==0x04){printf("本机:小端模式\n");}else{printf("本机:大端模式\n");}return0;}

本机运行结果:

四、结构体和共用体的区别
口诀:
结构体:各占各的,全部共存,内存相加(对齐后)
共用体:抢占同步一块,互斥共存,取最大(对齐后)

特性struct结构体union共用体
内存布局每个成员独立分配内存所有成员共享同一块内存
总大小=全部成员总和=最大成员大小(对齐后)
生命周期全部成员同时有效同一时刻只有一个成员有效
用途存放一组同时存在的属性互斥数据,类型双关,省内存
http://www.jsqmd.com/news/1397469/

相关文章:

  • 2026秦皇岛快艇出海观光哪家实惠精选指南 - 谁都没有我好看
  • Windows右键菜单优化:RightMenuMgr工具详解与高效管理策略
  • NHSE动物森友会存档编辑器完全指南:把几百小时的等待压缩成几分钟
  • 2026年国内云服务器厂商前十排名
  • 2026年新发布:宿迁阳台防护网片厂家精工打磨不锈钢网 工况再难也能刚-宇顺丝网制品 - 行业甄选汇
  • 深圳黄金变现不踩坑,全域正规连锁门店实操攻略 - 日常前沿快讯
  • 崩坏星穹铁道三月七小助手使用指南:四个场景看懂日常与周常的一键全自动托管
  • 北京灌装机价格走势:近年设备成本变化趋势 - 品牌龙虎榜
  • 为什么你的C盘越用越满?这款开源的Windows驱动清理工具3分钟帮你找回来
  • CentOS服务器JDK多版本全局管理:基于alternatives系统的优雅解决方案
  • OpenClaw AI智能体实战:从核心架构到60个自动化场景全解析
  • AMD Ryzen深度调试免费开源神器SMUDebugTool完整上手指南
  • SpringBoot整合ActiveMQ实战:从依赖配置到死信队列的避坑指南
  • 2026深圳大鹏新区同城搬家行业科普指南 - 深圳家顺兴搬家
  • Zabbix管理员必备:数据库操作恢复Web登录密码与用户名的完整指南
  • C语言梦开始的地方9:初识指针
  • 从0到1:用微信辅助功能实现自动抢红包的避坑指南
  • Windows平台pthread环境搭建:MinGW-w64方案与跨线程编程实践
  • 【Jetson】摄像头驱动移植流程记录
  • 在郑州卖黄金避坑!牢记3条回收准则,本地人常推荐正规回收渠道 - 资讯早知道
  • 深圳南山区同城搬家行业科普指南 - 深圳家顺兴搬家
  • UOS/Deepin双网卡策略路由配置:实现内外网同时访问
  • 中国裁判文书网1985-2023全国数据:处理、分析与应用实战指南
  • 水下通信技术全解析:声、光、电磁波实战选型指南
  • 猴痘病毒抗原MPV-Ag检测试剂说明书分享
  • 【AI Agent实战】元认知(Metacognition):让 AI Agent 学会“思考自己的思考“——从自我反思到自主纠错的智能进化之路
  • Some/IP协议详解:车载以太网服务化通信的核心原理与实践
  • 2026合肥中考100-200分,安徽建工公办免学费学技能+升学历! - 小张zc
  • 领嵌4G/5GAI边缘计算盒子多路视频算法分析10TOPS算力
  • 状态模式与策略模式深度辨析:从误用到重构的实战指南