覆盖union的值会引发未定义行为吗?结合代码实例咨询
联合体(Union)内存值变化的疑问解析
先看示例代码:
#include <stdio.h> #include <string.h> #include <stdint.h> int main() { union myUnion { int i; float f; char c; }; union myUnion u; u.i = 42; // 向联合体存入整数 printf("%d\n", u.i); // 输出42 u.f = 3.14; // 向联合体存入浮点数 printf("%f\n", u.f); // 输出3.140000 u.c = 'A'; // 向联合体存入字符 printf("%c\n", u.c); // 输出'A' printf("%d\n", u.i); // 输出1078523201 printf("%f\n", u.f); // 输出3.139969 }
核心疑问
前几次打印正常,但执行printf("%d\n", u.i);输出1078523201,理解是原int值被覆盖,按32位int格式解读当前内存内容。但后续打印u.f结果仍接近3.14,疑惑是不是浮点数被存在寄存器而非读取union的内存位置?
解析
首先明确联合体的核心特性:所有成员共享同一块内存空间,内存大小等于最大成员的尺寸(这里int和float都是4字节,char是1字节,所以整个union占4字节)。
我们一步步拆解内存变化:
- 赋值
u.i = 42:4字节内存中存储的是0x0000002A(小端模式下内存字节顺序为0x2A 0x00 0x00 0x00)。 - 赋值
u.f = 3.14:3.14的单精度浮点数二进制表示为0x4048F5C3(小端模式下内存字节顺序为0xC3 0xF5 0x48 0x40),此时整个4字节内存被完全覆盖。 - 赋值
u.c = 'A':'A'的ASCII码是65(0x41),char仅占1字节,只会修改内存的最低1字节(小端模式下的第一个字节),此时内存内容变为0x41 0xF5 0x48 0x40(对应十六进制值0x4048F541)。
关于u.i输出1078523201的原因
把修改后的4字节十六进制值0x4048F541转换为十进制,结果就是1078523201,完全符合“按int格式解读当前内存内容”的逻辑。
关于u.f仍接近3.14的原因
这和单精度浮点数的存储结构有关:
单精度浮点数用32位表示,分为3部分:1位符号位、8位指数位、23位尾数位。我们修改的0x41只是替换了原浮点数0xC3所在的最低有效字节,这部分对应的是尾数位的最低几位。尾数位的微小变化只会影响浮点数的精度,不会改变其整体的数量级,所以最终解析出的浮点数和原3.14非常接近,仅存在微小误差(3.139969)。
关于寄存器的猜测
不存在“浮点数保存在寄存器”的情况,printf("%f\n", u.f)是直接从union的内存地址读取4字节数据,再按单精度浮点数规则解析的。只是因为我们只改动了浮点数表示中对数值影响极小的部分,所以结果看起来和原数差不多。
内容的提问来源于stack exchange,提问作者palacetrading
相关产品推荐
相关产品推荐

