One of my friends pointed out from "Understanding and Using C Pointers - Richard Reese, O'Reilly publications" the second bullet point and I wasn't able to explain the first sentence from it. What am I missing?
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.
This is my code, not from the book and all pointers are having the same value and are 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");
}
Output:
0x7ffe1fbecfec 0x7ffe1fbecfec
0x7ffe1fbecfec
Equal
Equal
The following section from this Draft C11 Standard completely refutes the claim made (even with the clarification mentioned in the 'errata', in the comment by GSerg).
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.
Or, this section from the same draft Standard:
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 says:
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.
So, suppose we have:
int a;
void *p0 = &a;
void *p1 = &a;
Then, if p0
and p1
“point to the same object”, p0 == p1
must evaluate as true. However, one might interpret the standard to mean that a void *
does not point to anything while it is a void *
; it just holds the information necessary to convert it back to its original type. But we can test this interpretation.
Consider the specification that two pointers compare equal if they point to an object and a subobject at its beginning. That means that given int a[1];
, &a == &a[0]
should evaluate as true. However, we cannot properly use &a == &a[0]
, because the constraints for ==
for pointers require the operands point to compatible types or that one or both is a void *
(with qualifiers like const
allowed). But a
and a[0]
neither have compatible types nor are void
.
The only way for a fully defined situation to arise in which we are comparing pointers to this object and its subobject is for at least one of the pointers to have been converted either to void *
or to a pointer to a character type (because these are given special treatment in conversions). We could interpret the standard to mean only the latter, but I judge the more reasonable interpretation to be that void *
is included. The intent is that (void *) &a == (void *) &a[0]
is to be interpreted as a comparison of a pointer to the object a
to a pointer to the object a[0]
even though those pointers are in the form void *
. Thus, these two void *
should compare as equal.
TL/DR: the book is wrong.
What am I missing?
Nothing, as far as I can see. Even the erratum version presented in comments ...
A pointer to void will never be equal to another pointer to void.
... simply is not supported by the C language specification. To the extent that the author is relying on the language specification, the relevant text would be paragraph 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
is an object type, albeit an "incomplete" one. Pointers to void
that are valid and non-null are pointers to objects, and they compare equal to each other under the conditions expressed by the specification. The usual way that such pointers are obtained is by converting an object pointer of a different (pointer) type to void *
. The result of such a conversion still points to the same object that the original pointer did.
My best guess is that the book misinterprets the spec to indicate that pointers to void should not be interpreted as pointers to objects. Although there are special cases that apply only to pointers to void
, that does not imply that general provisions applying to object pointers do not also apply to void pointers.
A pointer is just an address in memory. Any two pointers are equal if they're NULL or if they point to the same address. You can go on and on about how that can happen with the language of structures, unions and so on. But in the end, it's simply just algebra with memory locations.
- A pointer to void will never be equal to another pointer. However, two void pointers assigned a
NULL
value will be equal.
Since NULL
is mentioned in that statement, I believe it is a mistype. The statement should be something like
NULL
pointer. However, two void pointers assigned a NULL
value will be equal.That means any valid pointer to void is never equal to NULL
pointer.