You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

覆盖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字节)。

我们一步步拆解内存变化:

  1. 赋值u.i = 42:4字节内存中存储的是0x0000002A(小端模式下内存字节顺序为0x2A 0x00 0x00 0x00)。
  2. 赋值u.f = 3.14:3.14的单精度浮点数二进制表示为0x4048F5C3(小端模式下内存字节顺序为0xC3 0xF5 0x48 0x40),此时整个4字节内存被完全覆盖。
  3. 赋值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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:57:03