【问题标题】:Is (void*) ptr == ptr always true?(void*) ptr == ptr 总是正确的吗?
【发布时间】:2019-10-23 22:51:34
【问题描述】:

我从last question 中删除了这个问题,因为我认为这是一个相当个人的问题。所以我在标准中找到了指针转换的段落,关于我的问题的段落是:

6.3.2.3

指针

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

...

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

现在它只声明

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

应该永远是真的,但是呢

(void*) ptr == ptr

没有明确说明这是对还是错。还是我误解了第 1 段?

【问题讨论】:

  • 我怀疑(void*) ptr == ptr(void*) ptr == (void*) ptr 相同,因为第二个操作数将被隐式转换为void* 以便进行比较。虽然不是 100% 确定...
  • 我相信比较应该是真的除非 ptr是一个函数指针,在这种情况下标准不保证它。
  • 嗯,这显然是真实的,或者未定义的行为。

标签: c pointers casting void-pointers pointer-conversion


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

【讨论】:

  • 请注意,这不适用于函数指针,因为它们不被视为指向“对象”。我不知道 OP 是否关心这个案子。
【解决方案2】:

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

(void *) ptr 肯定等于它自己,除非我们有一些无聊的幽默,比如 ptr 是一个扩展为具有副作用的表达式的宏,在不同的评估中会改变它的值,或者是一个不确定值的表达式,使用这是未定义的行为。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多