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
A pointer in a program that isn't associated with a data type is known as a void pointer in C. The void pointer points to the data location. The void pointer in C is a pointer that is not associated with any data types. It points to some data location in the storage.
void* is a "pointer to anything". void ** is another level of indirection - "pointer to pointer to anything". Basically, you pass that in when you want to allow the function to return a pointer of any type.
A void pointer is a pointer that can point to any type of object, but does not know what type of object it points to. A void pointer must be explicitly cast into another type of pointer to perform indirection. A null pointer is a pointer that does not point to an address.
A pointer to void means a generic pointer that can point to any data type. We can assign the address of any data type to the void pointer, and a void pointer can be assigned to any type of the pointer without performing any explicit typecasting.
Hence, dereferencing a void pointer is illegal in C. But, a pointer will become useless if you cannot dereference it back. To dereference a void pointer you must typecast it to a valid pointer type. What is a void pointer can you dereference a void pointer without knowing its type? 4 Answers.
Till now, we have studied that the address assigned to a pointer should be of the same type as specified in the pointer declaration. For example, if we declare the int pointer, then this int pointer cannot point to the float variable or some other type of variable, i.e., it can point to only int type variable.
2) The C standard doesn’t allow pointer arithmetic with void pointers. However, in GNU C it is allowed by considering the size of void is 1. For example the following program compiles and runs fine in gcc.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With