Dereferencing a float variable using a void pointer:
#include <stdio.h>
int main() {
float a = 7.5;
void *vp = &a;
printf("%f", *(float*)vp); /* Typecasting a void pointer to float for dereference */
printf("\n");
}
Output: 7.500000
Dereferencing a variable using an integer pointer:
#include <stdio.h>
int main() {
float a = 7.5;
int *ip = &a;
printf("%f", *(float*)ip); /* Typecasting an int pointer to float for dereference */
printf("\n");
}
Output: 7.500000
In both, the outputs are same. What is the reason to go for dereferencing of different datatype variable, when we are able to do by typecasting a normal pointer?
Why do we use a void pointer in C programs? We use the void pointers to overcome the issue of assigning separate values to different data types in a program. The pointer to void can be used in generic functions in C because it is capable of pointing to any data type.
Why we use void pointers? We use void pointers because of its reusability. Void pointers can store the object of any type, and we can retrieve the object of any type by using the indirection operator with proper typecasting.
You cannot. Dereferencing a void pointer requires an explicit cast beforehand. You can ofcourse cast it to any particular type and then dereference it without knowing its original type, but why you would want to do that is beyond me.
The compiler will not let you dereference a void* pointer because it does not know the size of the object pointed to.
Converting any data pointer to void*
pointer and back is guaranteed to give back original pointer.
From C11 standard draft N1570:
6.3.2.3 Pointers
- 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.
Converting data pointer to other data pointer than void*
(int*
in your example) may work. It depends on the compiler you are using and the system you are on. Not all systems might use same internal representation for different pointer types.
- A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned 68) 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 is different from strict aliasing rules.
float a = 7.5;
int *ip=&a;
int i = *ip; // Dereferenced using invalid type
Code above breaks strict aliasing rule as dereferenced type is not the same as the original type. This results in undefined behaviour and is always invalid code.
A void
pointer is a generic pointer which can hold the address of any type and can be typecast to any type.
In the first case, the program successfully compiled and ran without any warning or error, because using a void
pointer to convert from one pointer type to another and then storing or casting it to the final type is safe without losing data.
But in the second case the GCC compiler generated a warning
prog.c: In function 'main':
prog.c:5:9: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
int *ip=&a;
^
clang compiler:
warning: incompatible pointer types initializing 'int *' with an expression of type 'float *' [-Wincompatible-pointer-types]
int *ip=&a;
^ ~~
The C11 Standard, 6.3.2.3, paragraph 7:
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
A void
pointer is (sort of) untyped. It can point to anything without the compiler complaining. e.g. If you have an int
variable, you can safely create a void
pointer that points to this and pass it around. e.g.
int x = 10;
void *p = &x
is fine but
int x = 10;
float *p = &x;
will upset the compiler
This is especially useful for functions that operate on multiple pointer types or if you will decide what something is at runtime.
However, void pointers cannot be dereferenced (*
) directly because the compiler doesn't know their type. So,
printf("%d\n", *p);
will break if p is void pointer. We have to know the size of what it points to to dereference it and this is done using a manual type cast (like what you've done).
In your specific case, you have a pointer that points to a float which you type cast back into float before printing it. So, you will get the same output. The void *
pointer is not really playing a big role here.
An example of where you need a void *
is the malloc
function, If you look at the prototype, it returns a void *
. i.e. a block of raw memory. You need to typecast this as a concrete type before you can do pointer arithmetic and dereferencing.
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