这是什么意思:指向 void 的指针永远不会等于另一个指针?
What does this mean: a pointer to void will never be equal to another pointer?
我的一个朋友从“理解和使用 C 指针 - Richard Reese,O'Reilly 出版物”中指出了第二个要点,我无法解释 第一个 句起。我错过了什么?
Pointer to void
A pointer to void is a general-purpose pointer used to hold references to any data type. An example of a pointer to void is shown below:
void *pv;
It has two interesting properties:
- A pointer to void will have the same representation and memory alignment as a pointer to
char
.
- A pointer to void will never be equal to another pointer. However, two void pointers assigned a
NULL
value will be equal.
这是我的代码,不是书中的代码,所有指针都具有相同的值且相等。
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
void *p1 = (void*)&a;
void *p2 = (void*)&a;
printf("%p %p\n",p1,p2);
printf("%p\n",p);
if(p == p1)
printf("Equal\n");
if(p1 == p2)
printf("Equal\n");
}
输出:
0x7ffe1fbecfec 0x7ffe1fbecfec
0x7ffe1fbecfec
Equal
Equal
以下部分来自 this Draft C11 Standard completely refutes the claim made (even with the clarification mentioned in the 'errata', in the )。
6.3.2.3 Pointers
1 A pointer to void
may be converted to or from a pointer to any object type. A pointer to any
object type may be converted to a pointer to void
and back again;
the result shall compare equal to the original pointer.
或者,此部分来自同一标准草案:
7.20.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with
the property that any valid pointer to void
can be converted to this
type, then converted back to pointer to void
, and the result will
compare equal to the original pointer:
intptr_t
C 2018 6.5.9 6 说:
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
所以,假设我们有:
int a;
void *p0 = &a;
void *p1 = &a;
然后,如果p0
和p1
“指向同一个对象”,p0 == p1
必须评估为真。但是,有人可能会将标准解释为 void *
不指向任何东西,而它是 void *
;它只包含将其转换回其原始类型所需的信息。但是我们可以检验这个解释。
考虑两个指针比较相等的规范,如果它们在开头指向一个对象和一个子对象。这意味着给定 int a[1];
,&a == &a[0]
应该评估为真。但是,我们不能正确使用 &a == &a[0]
,因为 ==
对指针的约束要求操作数指向兼容类型,或者其中一个或两个都是 void *
(带有限定符 const
允许)。但是 a
和 a[0]
既没有兼容的类型,也没有 void
.
出现完全定义情况(我们正在比较指向此对象及其子对象的指针)的唯一方法是至少将其中一个指针转换为 void *
或指针到字符类型(因为这些在转换中得到特殊处理)。我们可以将标准解释为仅表示后者,但我认为更合理的解释是包含 void *
。目的是将 (void *) &a == (void *) &a[0]
解释为指向对象 a
的指针与指向对象 a[0]
的指针的比较,即使这些指针的形式为 void *
.因此,这两个 void *
应该比较相等。
TL/DR: 书错了
What am I missing?
据我所知,没有。即使是评论中出现的勘误版本...
A pointer to void will never be equal to another pointer to void.
... C 语言规范根本不支持。如果作者依赖语言规范,相关文本将是第 6.5.9/6 段:
Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and
a subobject at its beginning) or function, both are pointers to one
past the last element of the same array object, or one is a pointer to
one past the end of one array object and the other is a pointer to the
start of a different array object that happens to immediately follow
the first array object in the address space.
void
是一种对象类型,尽管是“不完整”的类型。指向有效且非空的 void
的指针是指向对象的指针,它们在规范表达的条件下相互比较相等。获得此类指针的通常方法是将不同(指针)类型的对象指针转换为 void *
。这种转换的结果仍然指向与原始指针相同的对象。
我最好的猜测是这本书误解了规范,指出指向 void 的指针不应被解释为指向对象的指针。尽管有一些特殊情况仅适用于指向 void
的指针,但这并不意味着适用于对象指针的一般规定也不适用于 void 指针。
指针只是内存中的一个地址。如果两个指针为 NULL 或指向同一地址,则它们相等。您可以继续讨论结构、联合等语言如何实现这一点。但最终,它只是带有内存位置的代数。
- A pointer to void will never be equal to another pointer. However, two void pointers assigned a
NULL
value will be equal.
由于该声明中提到了 NULL
,我认为这是一个错误输入。该声明应该类似于
- 指向 void 的指针永远不会等于
NULL
指针。但是,分配了 NULL
值的两个空指针将相等。
这意味着任何指向 void 的有效指针永远不会等于 NULL
指针。
我的一个朋友从“理解和使用 C 指针 - Richard Reese,O'Reilly 出版物”中指出了第二个要点,我无法解释 第一个 句起。我错过了什么?
Pointer to void
A pointer to void is a general-purpose pointer used to hold references to any data type. An example of a pointer to void is shown below:
void *pv;
It has two interesting properties:
- A pointer to void will have the same representation and memory alignment as a pointer to
char
.- A pointer to void will never be equal to another pointer. However, two void pointers assigned a
NULL
value will be equal.
这是我的代码,不是书中的代码,所有指针都具有相同的值且相等。
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
void *p1 = (void*)&a;
void *p2 = (void*)&a;
printf("%p %p\n",p1,p2);
printf("%p\n",p);
if(p == p1)
printf("Equal\n");
if(p1 == p2)
printf("Equal\n");
}
输出:
0x7ffe1fbecfec 0x7ffe1fbecfec
0x7ffe1fbecfec
Equal
Equal
以下部分来自 this Draft C11 Standard completely refutes the claim made (even with the clarification mentioned in the 'errata', in the
6.3.2.3 Pointers
1 A pointer to
void
may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer tovoid
and back again; the result shall compare equal to the original pointer.
或者,此部分来自同一标准草案:
7.20.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with the property that any valid pointer to
void
can be converted to this type, then converted back to pointer tovoid
, and the result will compare equal to the original pointer:
intptr_t
C 2018 6.5.9 6 说:
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
所以,假设我们有:
int a;
void *p0 = &a;
void *p1 = &a;
然后,如果p0
和p1
“指向同一个对象”,p0 == p1
必须评估为真。但是,有人可能会将标准解释为 void *
不指向任何东西,而它是 void *
;它只包含将其转换回其原始类型所需的信息。但是我们可以检验这个解释。
考虑两个指针比较相等的规范,如果它们在开头指向一个对象和一个子对象。这意味着给定 int a[1];
,&a == &a[0]
应该评估为真。但是,我们不能正确使用 &a == &a[0]
,因为 ==
对指针的约束要求操作数指向兼容类型,或者其中一个或两个都是 void *
(带有限定符 const
允许)。但是 a
和 a[0]
既没有兼容的类型,也没有 void
.
出现完全定义情况(我们正在比较指向此对象及其子对象的指针)的唯一方法是至少将其中一个指针转换为 void *
或指针到字符类型(因为这些在转换中得到特殊处理)。我们可以将标准解释为仅表示后者,但我认为更合理的解释是包含 void *
。目的是将 (void *) &a == (void *) &a[0]
解释为指向对象 a
的指针与指向对象 a[0]
的指针的比较,即使这些指针的形式为 void *
.因此,这两个 void *
应该比较相等。
TL/DR: 书错了
What am I missing?
据我所知,没有。即使是评论中出现的勘误版本...
A pointer to void will never be equal to another pointer to void.
... C 语言规范根本不支持。如果作者依赖语言规范,相关文本将是第 6.5.9/6 段:
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
void
是一种对象类型,尽管是“不完整”的类型。指向有效且非空的 void
的指针是指向对象的指针,它们在规范表达的条件下相互比较相等。获得此类指针的通常方法是将不同(指针)类型的对象指针转换为 void *
。这种转换的结果仍然指向与原始指针相同的对象。
我最好的猜测是这本书误解了规范,指出指向 void 的指针不应被解释为指向对象的指针。尽管有一些特殊情况仅适用于指向 void
的指针,但这并不意味着适用于对象指针的一般规定也不适用于 void 指针。
指针只是内存中的一个地址。如果两个指针为 NULL 或指向同一地址,则它们相等。您可以继续讨论结构、联合等语言如何实现这一点。但最终,它只是带有内存位置的代数。
- A pointer to void will never be equal to another pointer. However, two void pointers assigned a
NULL
value will be equal.
由于该声明中提到了 NULL
,我认为这是一个错误输入。该声明应该类似于
- 指向 void 的指针永远不会等于
NULL
指针。但是,分配了NULL
值的两个空指针将相等。
这意味着任何指向 void 的有效指针永远不会等于 NULL
指针。