C语言中同一块内存作为不同类型变量访问的高效实现方法
C语言中同一块4字节内存支持两种类型访问的最高效实现
最高效的实现方式是使用C语言原生的联合体(union),该方案完全没有额外运行开销,且符合C标准规范,不会出现未定义行为。
实现原理
联合体的所有成员共享同一块起始地址的内存空间,修改任意一个成员的值都会直接作用在共享内存上,其余成员访问时会自动同步最新的内存内容,正好匹配双向同步访问的需求。
注意事项
- 为了保证内存宽度严格为4字节,推荐使用
stdint.h头文件中的固定宽度整数类型,避免不同平台下unsigned long宽度不一致(部分64位平台unsigned long为8字节)的问题。 - 数组下标对应的字节位置和硬件的字节序强相关:用户示例中
L=300(0x0000012c)时c[3]为0x2c属于大端字节序的表现;如果是x86、ARM等默认小端字节序的平台,0x2c会对应c[0]。
代码示例
#include <stdint.h> // 定义联合体,两个成员共享4字节内存 union MemAlias { uint32_t L; // 对应4字节无符号整数类型 uint8_t c[4]; // 对应4字节char数组 }; int main(void) { union MemAlias mem; // 赋值整数值 mem.L = 300; // 内存对应十六进制为0x0000012c // 大端场景下c[3]为0x2c,小端场景下c[0]为0x2c mem.c[3] += 1; // 此时mem.L自动同步为301,符合预期 return 0; }
为什么不推荐指针强制转换的写法?
你可能见过类似unsigned long L; char *c = (char*)&L;的写法,这种写法虽然看起来也能实现需求,但违反了C标准的严格别名规则,属于未定义行为:当编译器开启高优化等级(如-O2及以上)时,可能会将L的值缓存到寄存器中,不会感知到c数组对内存的修改,导致读取L时拿到旧值,出现逻辑错误。
而联合体的类型双关用法是C标准明确支持的合法行为,不会出现上述问题,且访问效率和直接操作变量完全一致,是最优方案。
内容的提问来源于stack exchange,提问作者Don
相关产品推荐
相关产品推荐

