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

C语言中通过尾后地址匹配的指针写入数组是否为未定义行为?

结论

这个操作属于C标准规定的未定义行为,并非Clang的bug。

原因解释
  • 首先,数组尾后指针的解引用本身就是未定义行为。C标准明确允许生成数组的尾后指针,也允许用该指针做相等性比较,但任何对尾后指针的解引用操作都是非法的。你的代码逻辑中,进入if (ADDR_AFTER(first) == (uintptr_t)an_int)分支的前提就是an_int对应first数组的尾后地址,此时对an_int解引用赋值,本质就是对尾后指针的非法操作。
  • 其次,C标准没有对不同独立对象的内存排布做任何连续性承诺,编译器有权假定两个独立定义的全局数组first和second的地址不会重叠,也不会出现first的尾后地址刚好等于second的起始地址的情况。-O2优化下出现test: 1的输出就是这个优化假定的结果:编译器判定*an_int = 2的写入操作不会修改*second的值,因此将test函数中*second = 1后的返回操作直接优化为返回常量1,哪怕实际运行时内存中second的值已经被改写。
  • 关于uintptr_t类型转换的规则:C标准仅保证「将合法指针转换为uintptr_t后再转换回原指针类型,仍能正常访问原指针对应的对象」,从未规定「数值相等的uintptr_t转换回指针后,可以跨对象访问内存」。就算运行时first尾后地址的数值刚好等于second的起始地址,通过前者的转换结果访问second的行为仍然是未定义的。
  • UBSan的运行时报错也直接佐证了这一判定:它检测到你正在向一个没有为int对象预留空间的地址写入数据,哪怕该地址刚好属于另一个数组的空间,这种访问方式也不符合C标准的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:45:02