简体   繁体   English

当 (void *) p == (void *) *p - 标准对此有何评论?

[英]When (void *) p == (void *) *p - What does the Standard say about this?

Example:例子:

int a[99];
int (*p)[99] = &a;

// this prints 1
printf("%d\n", (void *) p == (void *) *p);

In general, if p is a pointer to an array, then both the object representations (ie the bit patterns) of p and *p are equal.通常,如果p是指向数组的指针,则p*p的对象表示(即位模式)是相等的。

I'm just lost and completely unsure about the portability of this behaviour.我只是失去了,完全不能确定这种行为的便携性。

So, I'm curious whether this behaviour is guaranteed by the Standard.所以,我很好奇这种行为是否受到标准的保证。 If so, could someone please quote all of the relevant paragraphs that guarantee it?如果是这样,有人可以引用所有保证它的相关段落吗?

This comparison is guaranteed to be 1.此比较保证为 1。

The relevant part of the C standard is section 6.5.9p6 regarding the equality operator and the comparison of pointers: C 标准的相关部分是关于相等运算符和指针比较的第 6.5.9p6 节:

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.两个指针比较相等当且仅当它们都是空指针,都是指向同一个对象的指针包括指向对象的指针和位于其开头的子对象)或函数,都是指向同一数组最后一个元素之后的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象开头的指针,该对象恰好紧跟地址空间中的第一个数组对象。

Take particular note of the passage in bold.请特别注意粗体的段落。 This means two things: 1) a pointer to a struct and a pointer to its first member (suitable converted) will compare equal, and 2) a pointer to an array and a pointer to its first member (again, suitable converted) will compare equal.这意味着两件事:1)指向结构的指针和指向其第一个成员(合适的转换)的指针将比较相等,2)指向数组的指针和指向其第一个成员的指针(再次,合适的转换)将比较平等的。

In your particular case, p points to an array and *p is the array itself, and using *p in an expression yields a pointer to its first member.在您的特定情况下, p指向一个数组, *p是数组本身,并且在表达式中使用*p产生一个指向其第一个成员的指针。 Both are converted to void * to give them a common type.两者都转换为void *以赋予它们一个通用类型。 So this comparison will always evaluate to 1.因此,这种比较将始终评估为 1。

In general, if p is a pointer to an array, then both the object representations (ie the bit patterns) of p and *p are equal.通常,如果p是指向数组的指针,则p*p的对象表示(即位模式)是相等的。

If p is a pointer to an array, then *p is the array.如果p是指向数组的指针,则*p是数组。 The bit representation of the array is the concatenation of the bit representations of the elements of the array (because C 2018 6.2.5 20 says an array is made of contiguously allocated objects).数组的位表示是数组元素的位表示的串联(因为 C 2018 6.2.5 20 说数组由连续分配的对象组成)。 The bits in the array are not generally equal to the bits in the pointer.数组中的位通常不等于指针中的位。

However, when an array is used in an expression other than as the operand of unary & or the operand of sizeof or as a string literal used to initialize an array, the array is automatically converted to a pointer to its first element.但是,当数组在表达式中用作一元&的操作数或sizeof的操作数或用于初始化数组的字符串文字以外的表达式时,该数组会自动转换为指向其第一个元素的指针。 The first element of the array *p is (*p)[0] , so *p is automatically converted to &(*p)[0] .数组*p的第一个元素是(*p)[0] ,因此*p会自动转换为&(*p)[0]

Then the question is whether (void *) p equals (void *) &(*p)[0] .那么问题是(void *) p是否等于(void *) &(*p)[0]

C 2018 6.3.2.3 1 tells us any pointer to an object type may be converted to void * . C 2018 6.3.2.3 1 告诉我们任何指向对象类型的指针都可以转换为void * However, it does not tell us what the results of comparisons are while the pointer is void * .但是,当指针为void * ,它并没有告诉我们比较的结果是什么。 It does tell us that converting the void * back to its original type yields a pointer that compares equal to the original.它确实告诉我们,将void *转换回其原始类型会产生一个与原始类型相等的指针。

C 2018 6.5.9 6 tells us “Two pointers compare equal if and only if …, both are pointers to the same object (including a pointer to an object and a subobject at its beginning)…” (I elided some other cases that are not of concern here.) What are we to make of this given two void * ? C 2018 6.5.9 6 告诉我们“两个指针比较相等当且仅当……,两者都是指向同一个对象的指针(包括指向对象的指针和开头的子对象)……”(我省略了其他一些情况这里无关紧要。)给定两个void *我们该怎么做? It seems the intent is for a pointer to “point to an object” even if it is currently in the form of a void * .似乎意图是让指针“指向一个对象”,即使它当前是void *的形式。 Then (void *) p points to the array and (void *) &(*p)[0] points to a subobject at its beginning, so they compare equal.然后(void *) p指向数组并且(void *) &(*p)[0]指向其开头的子对象,因此它们比较相等。

The semantics would be clearer with (char *) p == (char *) *p because C 2018 6.3.2.3 7 tells us that converting to char * produces a pointer to the first byte of an object, and the first byte of an array is the same as the first byte of its first element.使用(char *) p == (char *) *p的语义会更清晰,因为 C 2018 6.3.2.3 7 告诉我们转换为char *会产生一个指向对象第一个字节的指针,以及一个指向对象的第一个字节的指针。数组与其第一个元素的第一个字节相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM