我从last question中删除了这个问题,因为我认为这是一个单独的问题。因此,我在标准中找到了有关指针转换的段落,有关我的问题的段落是:
6.3.2.3
指针
1指向void的指针可以转换为任意指针 对象类型。指向任何对象类型的指针都可以转换为 指向void并再次返回的指针;结果应相等 指向原始指针。
...
4将空指针转换为另一种指针类型会产生 该类型的空指针。任何两个空指针都应进行比较 相等。
现在仅声明
(originaltype*)((void*)ptr) == ptr
永远都是真实的,但是那怎么办
(void*) ptr == ptr
没有明确说明是否为真或假。还是我误解了第一段?
答案 0 :(得分:4)
C 2018 6.5.9讨论了==
。第2款指定了约束,并且(void *) ptr == ptr
满足约束,因为其中一个选项是“一个操作数是指向对象类型的指针,而另一个是指向void
的合格或不合格版本的指针”。然后第5段说:“……如果一个操作数是指向对象类型的指针,而另一个是指向void的合格或不合格版本的指针,则前者将转换为后者的类型。”
因此,在(void *) ptr == ptr
中,正确的操作数将转换为(void *)
,因此该表达式等效于(void *) ptr == (void *) ptr
,我们可能希望它的计算结果为true。
严格来说,有关指针转换的子句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
始终为真。
答案 1 :(得分:1)
*如果ptr
是指向对象类型的指针,则(void *) ptr == ptr
等效于(void *) ptr == (void *) ptr
。右侧的ptr
被隐式转换为void *
。 (如果它是指向const
或volatile
限定类型的指针,则这些限定符将在隐式转换中丢失。)
(void *) ptr
肯定等于自己,除非我们招待闲散的幽默,例如ptr
是一个宏,扩展为具有副作用的表达式,该副作用会改变其在不同求值上的值,或者是不确定值,其用法是不确定的行为。
如果ptr
是指向函数的指针,则(void *) ptr == ptr
需要诊断;但显然讨论是关于对象类型的。