C语言中union(共用体)的成员值是如何发生变化的?
问题分析
你给出的代码如下:
#include <stdio.h> int main() { typedef union{ int a ; char c; float f; } myu; myu sam; sam.a = 10; sam.f=(float)5.99; sam.c= 'H'; printf("%d\n %c\n %f\n",sam.a,sam.c,sam.f); return 0; }
出现你观察到的输出,核心原因是C语言**共用体(union)**的内存共享特性,具体逻辑如下:
- 共用体的所有成员共享同一块起始地址的内存空间,整个共用体的大小等于所有成员中占用空间最大的那个的大小。在常见的x86平台下,int、float均占用4字节,char占用1字节,因此这个共用体总大小为4字节,任意时刻只会保留最后一次赋值的成员的有效内容,更早的赋值会被覆盖。
- 你的赋值顺序为
sam.a = 10→sam.f = (float)5.99→sam.c = 'H':- 给a赋值10时,4字节内存为int 10对应的二进制值
0x0000000A - 给f赋值5.99时,整个4字节被完全覆盖为float 5.99对应的IEEE754单精度编码,此时a的原有值已经完全失效
- 最后给c赋值'H'(ASCII码为
0x48),因为char只占用1字节,只会修改4字节内存中最低地址的1个字节(x86平台为小端字节序,该位置对应int的最低位字节、float尾数的最低8位),剩余3个字节仍保留float 5.99的编码内容
- 给a赋值10时,4字节内存为int 10对应的二进制值
- 两个输出现象的具体原因:
- int类型a的取值大幅变化:int会把整个4字节内存当成一个整体的整数解析,当前4字节中只有最低1字节是
0x48,剩下3字节都是float 5.99的高位编码,组合出来的整数值自然和原有10完全无关,就是你看到的大数1086303816 - float类型f的取值几乎和原值一致:单精度float的32位结构为1位符号位、8位阶码、23位尾数,你修改的最低1字节属于尾数的最后8位,只会影响浮点数精度的最低位,带来的误差极小,因此输出结果
5.990025和原值5.99几乎一致。
- int类型a的取值大幅变化:int会把整个4字节内存当成一个整体的整数解析,当前4字节中只有最低1字节是
内容的提问来源于stack exchange,提问作者kakarot-757
相关产品推荐
相关产品推荐

