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

将union指针直接转换为其数组成员元素类型指针的合法性探究

关于Union指针转换与访问的合法性分析

针对你提出的两个问题,结合C标准规则逐一解答:

1. 直接将union Obj64*转换为uint16_t*是否合法?

合法。

根据C标准规定:指向union对象的指针可以转换为指向其任意成员类型的指针,反之亦然。你的Obj64 union包含uint16_t u16[4]成员,指向数组类型的指针可隐式衰减为指向其元素类型的指针(uint16_t*)。同时:

  • union对象的起始地址与所有成员的起始地址完全重合;
  • 你的static_assert保证了union无尾部填充,且uint64_t的对齐要求不低于uint16_t,转换后的uint16_t*满足对齐要求。

直接转换(uint16_t *)union_ptr等价于先将union指针转为指向uint16_t[4]的指针,再通过数组到指针的衰减得到uint16_t*,完全符合C标准的指针转换规则。

2. 两种方式获取的指针在未定义行为上的差异

两种指针的核心差异在于有效访问范围的定义:

  • 通过union_ptr->u16获取的指针,本质是指向u16数组对象的指针。该数组的有效索引范围是0~3,访问union_ptr->u16[4]属于数组越界访问,是明确的未定义行为——编译器可能进行激进优化、导致内存访问错误或其他不可预测的结果。
  • 直接转换得到的uint16_t*,指向的是union对象的起始内存。如果内存区域是连续的Obj64缓冲区,((uint16_t *)union_ptr)[4]本质是访问下一个Obj64对象的u16[0]成员。由于uint16_t是union的成员类型之一,根据strict aliasing规则,用uint16_t*访问union对象的内存合法;再加上static_assert保证每个union无填充,连续布局的union之间无额外内存间隙,因此该访问属于定义行为。

需注意,这种跨union访问仅在内存连续且无填充的前提下有效,若union存在未预期填充(已被断言排除),则会触发未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:28:13