In below code, how can void pointer p store address of i? What is the meaning of "*(float *)p" inside printf() ?
#include
void main()
{
int i = 10;
void *p = &i;
printf("%f\n", *(float *)p);
}
In below code, how can void pointer p store address of i? What is the meaning of "*(float *)p" inside printf() ?
#include
void main()
{
int i = 10;
void *p = &i;
printf("%f\n", *(float *)p);
}
A void*
can store any address. It's a "generalized pointer" basically. You can cast back the void*
to the type you saved into it to get a useful type out of it and do things with it like pointer arithmetic or dereferencing the pointer. The pointer itself doesn't know anything about what type it stores and thus you have to tell it what type it's pointing to so. It's lack of type makes it dangerous since it's the programmer's job to remember what type the pointer points to.
In your case, you make p
point to the address of i
which is an int
and then you try to print out the pointee of p
as a float
while you didn't assign it to the address of a float
in the first place. This is undefined behaviour and a good example of the dangers of a void*
in inexperienced hands.
In C void* can point to any type of memory location. You can assign void* to a variable of type int*, double*, char*.., etc. Generally void* is used to pass parameters to the function who type is not know at the time of defining.
But You can have any variable of type void. So at the time of dereferencing you have to cast a void* to some pointer type but not void*.
so by *(float *)p
(which is undefined) you are casting p(which is void* type) to float* type, then you are dereferencing it to double(But memory is actually int). So that it expects float type variable at the memory it is pointing to.
how can void pointer
p
store address ofi
?
A void pointer can point to any data pointer. See C11 draft, 6.3.2.3. So,
void *p = &i;
simply makes p
point to the address of object i
.
You can later safely convert it back to an int*
. For example,
int i = 10;
void *p = &i;
int *j = p; /* j now point to &i */
or you can directly cast p
and use it:
printf("%d\n", *((int*) p));
This is all fine.
What is the meaning of "*(float *)p" inside printf() ?
It's an attempt to reinterpret an int
object as a float
object which isn't allowed. In this statement:
printf("%f\n", *(float *)p);
You are casting p
, a void*
, to a float*
which may be undefined because the object p
points to is an int
and you are attempting to
reinterpret it as if it's a float
object. From C11 draft, 6.3.2.3:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
This also violates C11 draft, 6.5.7 as int*
and float*
are distinct types and are not compatible with each other.