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

C/C++中读写联合不同类型成员的未定义行为差异问询

联合跨成员访问的未定义行为分析

我们直接从示例代码开始:

#include <stdio.h>
#include <stdbool.h>

typedef union {
    bool b;
    int i;
} boolIntUnion;

int main(void) {
    boolIntUnion val;

    val.i = 0;
    printf("i = %d; %s\n", val.i, ((val.b)? "true" : "false"));
    
    val.i = 1;
    printf("i = %d; %s\n", val.i, ((val.b)? "true" : "false"));
    
    val.i = 2;
    printf("i = %d; %s\n", val.i, ((val.b)? "true" : "false"));
}

核心结论:该用法属于未定义行为

无论是C还是C++标准,这种联合跨成员访问的行为都被归类为未定义行为,具体依据如下:

C标准视角

根据C17标准§6.5.2.3第3款,当访问联合的某一成员时,若最后一次写入的是另一个成员,仅当两个成员类型兼容、或为指向兼容类型的指针、或其中一个是指向字符类型的指针时,访问行为才合法。
此处bool与int既不兼容,也不符合例外条件,因此整个跨成员访问的行为属于未定义行为。编译器可自由选择处理逻辑:

  • GCC和MSVC选择将int的整体非零性作为bool的真值判断依据,因此i=2时b返回true;
  • Clang则严格读取bool成员对应的内存字节(通常为1字节),小端系统下i=2的最低字节值为0,因此b返回false。两种实现均符合标准对未定义行为的允许范围。

C++标准视角

C20标准§11.4.10第1款规定,联合中只有最后写入的成员为"活跃成员",访问非活跃成员的行为属于未定义行为,除非成员满足特定的类型兼容条件(如共用初始序列),而bool与int并不满足该条件。因此**在C中该代码同样属于未定义行为**。

建议

若需要确定的行为,应避免联合跨成员访问,改用显式转换逻辑,例如:

val.b = (val.i != 0);

内容的提问来源于stack exchange,提问作者0xLeon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:50:48