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

📅 2026/8/15 10:11:11
C语言中的共用体(联合体)union
在定义结构体和共用体时都是{}里面写成员都是自定义复合类型都可以嵌套、都可以做数组、指针。上节我们重点分析了结构体本文将主要讲共用体。一、定义共用体是一种自定义数据类型多个成员共享同一块空间。同一时刻只有一个成员是有效的给一个成员赋值会覆盖其他成员的值。共用体占用的内存大小等于它最大成员所占的字节数。#includestdio.h#includewindows.h#includemath.huniondata{inti;charc;floatf;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);uniondata d;printf(共用体data占%d字节\n,sizeof(d));d.i0x68;printf(i%lx,c%c\n,d.i,d.c);d.f3.14f;//覆盖整个内存printf(f%f,i%lx\n,d.f,d.i);return0;}运行结果赋值完d.f之后再读d.i属于类型双关C标准未定义这种行为只是大部分编译器可以跑。对于值的改变我们通过下面这个例子可以清晰的看到后面成员变量的赋值直接把原来的值进行了部分覆盖#includestdio.h#includewindows.h#includemath.huniondata{inta;shortb;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);uniondata s1;s1.a0x01020304;s1.b0x0102;printf(a0x%X\n,s1.a);return0;}运行结果二、使用场景1、类型双关把同一块内存以不同类型视角解读。eg把float二进制位当作整数查看unionu{floatff;unsignedintii;};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);unionu test;test.ff1.0f;printf(ff%f,ii%lx\n,test.ff,test.ii);return0;}运行结果2、节省空间多个变量不会同时使用放在union共用一块内存减少内存占用。structmag{inttype;uniondata{intival;floatfval;charcval;};};例如type0可以代表ivaltype1代表fvaltype2代表cvalMsg结构体必须带type标记工程上用union一定要加标记位否则不知道哪个成员有效。3硬件、网络协议、二进制报文解析协议字段中同一个位置根据标志位不同代表不同含义用union非常适合4寄存器操作嵌入式硬件寄存器既可以整体读写也可以按位/字节访问使union变量互斥不同时使用需要同一块内存做多种类型解释内存紧张嵌入式三、注意事项1、同一时刻只有一个成员有效**容易忽视再重复**2、大小是最大成员大小但是考虑内存对齐unionu{chararr[5];inta;}上面最大成员是5字节但是对齐是按照int(4),sizeof(U)8,不是53、不要混用指针不要拿union不同成员的指针随意强制转化容易对齐问题4、联合体不能直接整体比较if(u1u2),C语言不支持需要自己逐个成员对比5、大小端问题CPU内部寄存器是按照bit取存储数据但是CPU内部寄存器资源有限需要把计算好的数据放到内存中对于内存来说它没有bit位的概念是按照字节编号地址来寻址。把寄存器中数据存到内存按照哪种顺序保存就是大小端的问题。小端模式数据的高位存到内存的高地址数据的低位到内存的低地址现阶段使用小端的比较多。大端模式数据的高位存到内存的低地址数据的低位存到内存的高地址。用union拆分字节看底层二进制程序受CPU大小端影响跨平台代码要小心。判断大小端的方法#includestdio.h#includewindows.h#includemath.hunionEndianCheck{unsignedintval;unsignedcharbytes[4];};intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);unionEndianCheck test;test.val0x01020304;printf(val0x%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共用体内存布局每个成员独立分配内存所有成员共享同一块内存总大小全部成员总和最大成员大小对齐后生命周期全部成员同时有效同一时刻只有一个成员有效用途存放一组同时存在的属性互斥数据类型双关省内存