C语言union返回后内部struct成员值不符合预期问题排查
错误核心原因
你的代码问题和结构体定义在union内部/外部没有任何关系,本质是对C语言**union(共用体)**的内存规则理解错误:
- union的所有成员共享同一块内存空间,内存总大小等于占用空间最大的成员的大小
- 对任意一个union成员赋值,都会覆盖共享内存中对应位置的原有数据,同一时间只有最后一次被赋值的成员的值是可靠的
结合你的代码具体分析:
- 你定义的
ku_type共用体中,sd结构体包含2个int类型成员(常规环境下每个int占4字节,整个sd占8字节),id是int类型占4字节。两个成员的内存起始地址完全重合,id占用的内存位置,刚好就是sd结构体第一个成员sd.x所在的前4字节。 - 在
kuReturner函数中你的赋值顺序是:- 先给
ku.sd.x赋值11,此时前4字节存11 - 再给
ku.sd.y赋值22,此时后4字节存22 - 最后给
ku.id赋值99,这一步直接把前4字节原来存的11覆盖成了99
- 先给
- 你最后读取
ku.sd.x的时候,读的就是前4字节被覆盖后的值99,这完全符合C语言的标准行为,不是编译器或者代码逻辑的其他问题。
修正方法
如果你需要同时保存sd.x、sd.y、id三个独立的值,不要使用union,改用struct(结构体)定义类型即可——结构体的每个成员占用独立的内存空间,赋值不会互相覆盖。参考修正后的代码:
#include <stdio.h> // 把union替换成struct,成员内存独立 typedef struct ku { struct { int x; int y; } sd; int id; } ku_type; ku_type kuReturner() { ku_type ku; ku.sd.x = 11; ku.sd.y = 22; ku.id = 99; return ku; } int main() { ku_type ku; ku = kuReturner(); // 此处打印会得到预期值11 printf("%d", ku.sd.x); return 0; }
补充:如果你确实要利用union的内存复用特性,必须遵守“写哪个成员,之后就读哪个成员”的规则,跨成员读取共享内存的值不属于C标准保障的可预期行为。
内容的提问来源于stack exchange,提问作者Manium
相关产品推荐
相关产品推荐

