Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C (void*)ptr==ptr是否始终为真?_C_Pointers_Casting_Void Pointers_Pointer Conversion - Fatal编程技术网

C (void*)ptr==ptr是否始终为真?

C (void*)ptr==ptr是否始终为真?,c,pointers,casting,void-pointers,pointer-conversion,C,Pointers,Casting,Void Pointers,Pointer Conversion,我把这个问题删掉了,因为我认为这是一个比较个别的问题。因此,我在标准中找到了指针转换的段落,关于我的问题是: 6.3.2.3 指针 1指向void的指针可以转换为指向任意 对象类型。指向任何对象类型的指针都可以转换为 指向void并再次返回的指针;结果应相等 指向原始指针 4将空指针转换为另一个指针类型 该类型的空指针。任何两个空指针都应进行比较 平等 现在它只说 (originaltype*)((void*)ptr) == ptr 永远都是真的,但那又如何呢 (void*) 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
,我们可以预期它的计算结果为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
总是正确的。

*如果
ptr
是指向对象类型的指针,那么
(void*)ptr==ptr
就相当于
(void*)ptr==(void*)ptr
。右侧的
ptr
被隐式转换为
void*
。(如果它是指向
const
volatile
限定类型的指针,则这些限定符将在隐式转换中丢失。)

(void*)ptr
当然等于它本身,除非我们喜欢无聊的幽默,比如
ptr
是一个宏,它扩展到一个表达式,在不同的计算中会改变它的值,或者是一个不确定值的表达式,它的使用是未定义的行为


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

我怀疑
(void*)ptr==ptr
(void*)ptr==(void*)ptr
相同,因为为了进行比较,第二个操作数将隐式转换为
void*
。但不是100%确定……我认为比较应该是正确的,除非
ptr
是函数指针,在这种情况下,标准不能保证它。很明显,它要么是正确的,要么是未定义的行为。请注意,这不适用于函数指针,因为它们不被视为指向“对象”。我不知道OP是否关心这个案子。