2个回答

4
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”至少有时为真。这是怎么可能的?(假设ptr不是空指针),(void *) ptr也不是空指针,我们也不希望这种情况被包含在“一个数组的末尾和另一个数组的开头”的情况中。因此,我们期望当“(void *)ptr ==(void *)ptr”评估为真时,它必须处于“指向同一对象”或“指向同一数组对象的最后一个元素”的情况下。那似乎是唯一合理的解释标准的方式。如果是这样的话,则该情况(无论哪种情况适用于某些情况)必须始终适用,并且“当且仅当”告诉我们,“(void *)ptr ==(void *)ptr”始终为真。

请注意,这不适用于函数指针,因为它们不被认为指向一个“对象”。我不知道 OP 是否关心这种情况。 - Tom Karzes

1
如果ptr是指向对象类型的指针,则(void *) ptr == ptr等同于(void *) ptr == (void *) ptr。右侧的ptr会被隐式转换为void *。(如果它是指向constvolatile限定类型的指针,则这些限定符在隐式转换中丢失。)
除非我们考虑到ptr是一个宏,扩展为具有副作用的表达式,在不同的评估中更改其值,或者是一个不确定值的表达式,使用它是未定义行为,否则(void *) ptr肯定等于自己。
如果ptr是指向函数的指针,则(void *) ptr == ptr需要进行诊断;但很明显讨论是关于对象类型的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接