C 的有效类型规则(上):编译器凭什么假设两个指针不重叠
来源:uecker.codeberg.page — 2026-10-31
📋 概述
Martin Uecker 讲解 C 语言的「有效类型」规则。这套规则从 ANSI X3.159-1989 就存在,是类型别名分析(TBAA)的基础:对象若以某个声明类型存在,用不兼容的类型去访问它便是未定义行为。他用 foo(int *p, float *q) 的例子说明编译器为何能直接把常量 3 返回而不重读 *p——如果两次访问确实重叠,行为未定义,那么返回 3 也是合法结果之一,语言语义学者把这叫 refinement。文章随后解释 C99 为支持没有声明类型的堆内存而引入的类型变更存储规则:用非字符类型的左值写入时,该类型就成为对象的有效类型,直到下一次写入。
🔑 核心要点
- 有效类型规则早在 ANSI X3.159-1989 就写下了,是类型别名分析(TBAA)的依据。
- 例子中编译器直接返回 3、不再重读 *p:重叠访问会构成未定义行为,返回 3 属于允许行为的子集。
- 语义学者称之为 refinement(精化):具体行为落在允许行为集合内即可。
- 起作用的是访问时所用左值的类型;指针变量本身的类型、函数参数类型都不违规,类型转换本身也不是别名违规。
- C99 为支持没有声明类型的堆内存,引入类型变更存储:写入即确立有效类型,直到下一次写入。
- 因此同一块内存在程序执行期间被两种不兼容类型访问,也可以是合法行为,很多自定义分配器正依赖这一点。
💡 金句
如我们所知,市场偏好优化胜过安全。
👍 0
👎 0
← 返回 Lobsters 首页