编码(一):C 指针与地址的差别
我们假设地址的确是指针,同时把这个命题称作命题:“地址与指针是同一的,亦即等价的”——首先,这个命题实际上承认了“地址”和“指针”是两个独立的对象,因为只有这样我们才能讨论“地址”和“指针”之间的关系是等价的还是不等价的。我们把“地址与指针是两个独立的对象”当作一个结论保留下来,并把它称作推论。其次,我们发现这个命题实际上是模糊的。总的来说,这个“命题”能分为这三个命题,分别为命题 1、2、3。显然,只有当命题 1、2、3 都为真时,命题才为真:
- 如果这里的“指针”指的是“指针类型的话”,那么立即能发现,由于在 C 语言中,类型系统承担了数据的语义,所以这里的“等价”关系表示“语义上的同一”——我们将这个命题称作命题 1,并将它保留下来。同时,根据推论所述,这个命题隐含了一个前提:“指针”和“地址”都有一个独立的类型,但由于 C 标准没有规定一个专门存储地址的类型,比如
addr_t什么的。所以在命题 1 中,“地址是指针”在命题逻辑上不合法,无法被常规的形式逻辑体系解释。我们现在把这一个结论称为推论 1:“命题‘指针的语义等价于地址的语义’未定义,亦即不可解释——由于后者与前者不在同一范畴中”,保留下来; - 另一个可能是:命题中的“地址”和“指针”都指的是“数据结构”,那么立即能发现,这里的“等价”关系为“表示等价”,亦即“地址是指针”的意思即是“地址与指针相同,它们所指的数据都是一串代表内存中的地址的位流”——我们将这个命题称作命题 2,并将它保留下来。一个明显的事实是:这总是平凡地为真的。我们现在把这一个结论称为推论 2:“命题‘指针的表示等价于地址的表示’平凡地为真”,保留下来;
- 最后一个可能是:命题中的“地址”与“指针”之间的等价关系是“操作”上的等价,亦即此命题陈述了如下这个命题:“凡是可以对指针做的操作,也可以对地址做;反之亦然”——我们把它称为命题 3,保留下来。首先,C 语言中指针可以解引用、进行有限的算术运算、参与别名分析,但是我们立即发现,C 语言不存在“地址对象”这一作为独立对象的实体,有的只是一串被赋予了地址语义的“整型”,通过
intptr_t或uintptr_t等类型“表现”出来。我们可以立即发现,对于这一情况,指针所能进行的操作集合是地址所能进行的操作集合的超集,亦即命题 3总是为假。我们将这个结论保留下来,称为推论 3:“命题‘凡是可以对指针做的操作,也可以对地址做;反之亦然’为假”,保留下来。
如果我们考察这三个命题,就会发现命题 1 ∧ 命题 2 ∧ 命题 3 为假,亦即命题(“地址与指针是同一的,亦即等价的”)为假。我们将这一结论称为结论,保留下来。
实际上,命题 1、2、3 与其结论能用如下表格呈现出来,这个表格清晰的展现了地址与指针的差别:
| 层次 | 地址 | 指针 |
|---|---|---|
| CPU | 位流 | 位流 |
| 操作 | 整型* | 指针 |
| 语言 | DNE | 类型 |
*: 无类型的位流在此被语言抽象为整型。
感 谢 您 的 阅 读
订阅 RSS 源