C语言 (无效*)ptr == ptr 总是为真吗?



我把这个问题从最后一个问题中删除了,因为我认为这是一个单独的问题。所以我在标准中找到了指针转换的段落,关于我的问题的段落是:

6.3.2.3

指针

1 指向 void 的指针可以转换为指向任何 对象类型。 指向任何对象类型的指针都可以转换为 指向 void 并再次返回的指针; 结果应相等 到原始指针。

4 将一个空指针转换为另一个指针类型会产生 该类型的空指针。任何两个空指针应比较 平等。

现在它只声明

(originaltype*)((void*)ptr) == ptr

永远是真的,但呢

(void*) ptr == ptr

没有明确说明这是真的还是假的。还是我误解了 1 段?

C 2018 6.5.9 讨论了==.第 2 段指定了约束,(void *) ptr == ptr满足约束条件,因为其中一个选项是"一个操作数是指向对象类型的指针,另一个是指向void的限定或非限定版本的指针"。然后第5段说"...如果一个操作数是指向对象类型的指针,另一个操作数是指向 void 的限定或非限定版本的指针,则前者将转换为后者的类型。

因此,在(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计算为 true 时,一定是因为它处于"指向同一对象的指针"或"指向同一数组对象案例的最后一个元素的指针"中。这似乎是解释标准的唯一合理方式。如果是这样,那么这种情况(无论哪种情况有时适用)必须始终适用,而"当且仅当"告诉我们(void *) ptr == (void *) ptr总是正确的。

*如果ptr是指向对象类型的指针,则(void *) ptr == ptr等效于(void *) ptr == (void *) ptr。 右侧的ptr隐式转换为void *。(如果它是指向constvolatile限定类型的指针,则这些限定符在隐式转换中丢失。

(void *) ptr当然等于它自己,除非我们接受闲散的幽默,比如ptr是一个宏观扩展到一个有副作用的表达,在不同的评估中改变其价值,或者是一个不确定价值的表达,其使用是未定义的行为。

如果ptr是指向函数的指针,那么(void *) ptr == ptr需要诊断;但很明显,讨论是关于对象类型的。

相关内容

  • 没有找到相关文章

最新更新