void*
pointers precede C ++ and templates as a mechanism for dealing with "generic" types in C. To be more specific void
represents the absence of type, which can be understood as the presence of any kind.
As you have already discovered, you can assign int
, char
or any other type to void*
.
With void*
functions that do not need to know the type details can do their job. The programmer, who knows the type, can do the necessary casts when needed ... See what absence of types basically places the typing responsibility on the programmer's back.
Why is this useful?
One of the best examples of using void*
is the qsort
function whose signature is:
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
With qsort
we can sort an array base
of any type. You just need to define a function of type int compar (const void* p1, const void* p2)
able to compare the types of array base
.
Example:
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
//...
int values[] = { 40, 10, 100, 90, 20, 25 };
qsort (values, 6, sizeof(int), compare);
You could have a method for comparing char*
, or maybe for a specific type of struct
or something else. Thanks to void
pointers the qsort
function is "generic".
But what about functions that return void pointers *?
The idea is the same. Generic APIs can work with multiple return types. A good example is the int pthread_setspecific(pthread_key_t key, const void *value)
and void *pthread_getspecific(pthread_key_t key)
function pair of% pthreads.h
. You can store and retrieve any type of value thanks to the use of void*
.
Other good examples are the ** alloc * functions as well mentioned in the previous answers. In c you do not and should not cast from the result of malloc
(this has changed in C ++):
// C
int *arr= malloc(sizeof(int)*length);
// C++ escrito para ser compatível com C
int *arr= (int *)malloc(sizeof(int)*length);
// C++ "de verdade"
int *arr= new int[length];
// C++11 - Melhor ainda, esqueça o delete
std::unique_ptr<int[]> arr(new int[10]);