C 2018 6.5.9 讨论==
。第 2 段指定了约束,并(void *) ptr == ptr
满足约束,因为其中一个选项是“一个操作数是指向对象类型的指针,另一个是指向限定或非限定版本的指针void
”。然后第 5 段说“……如果一个操作数是指向对象类型的指针,而另一个是指向 void 的限定或非限定版本的指针,则前者将转换为后者的类型。”</p>
因此,在 中(void *) ptr == ptr
,右操作数被转换为(void *)
,所以表达式等价于(void *) ptr == (void *) ptr
,我们可以预期它的计算结果为真。
严格来说,关于指针转换的子句 6.3.2.3 只告诉我们转换(void *) ptr
回其原始类型的结果将比较等于ptr
. 它没有告诉我们关于 的值的任何其他信息(void *) ptr
,因此,仅考虑这个子句,两个不同的实例可能(void *) ptr
会产生不同的结果,只要它们包含足够的信息来产生与原始值相等的东西ptr
当转换回来。
回到 6.5.9,第 6 段告诉我们:
两个指针比较相等当且仅当两者都是空指针,两者都是指向同一个对象(包括指向对象的指针和在其开头的子对象)或函数,两者都是指向同一数组最后一个元素之后的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的开头的指针,该数组对象恰好紧随地址空间中的第一个数组对象。
现在,我们当然希望(void *) ptr == (void *) ptr
至少在某些时候是真的。这怎么可能?(void *) ptr
不是空指针(假设ptr
不是),我们也不希望这种情况被一个数组的结尾和另一种情况的开始所覆盖。所以我们期望,当(void *) ptr == (void *) ptr
计算结果为真时,一定是因为它处于“指向同一对象的指针”的情况下或“指向同一数组对象最后一个元素的指针的情况”。这似乎是解释标准的唯一合理方式。如果是这样,那么这种情况(无论哪种情况有时适用)必须始终适用,并且“当且仅当”告诉我们这(void *) ptr == (void *) ptr
始终是正确的。