This is one of my favourite kind of questions because at first I was also so confused about void pointers.
Like the rest of the Answers above void *
refers to a generic type of data.
Being a void pointer you must understand that it only holds the address of some kind of data or object.
No other information about the object itself, at first you are asking yourself why do you even need this if it's only able to hold an address. That's because you can still cast your pointer to a more specific kind of data, and that's the real power.
Making generic functions that works with all kind of data.
And to be more clear let's say you want to implement generic sorting algorithm.
The sorting algorithm has basically 2 steps:
- The algorithm itself.
- The comparation between the objects.
Here we will also talk about pointer functions.
Let's take for example qsort built in function
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
We see that it takes the next parameters:
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
And based on the article that I referenced above we can do something like this:
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Where you can define your own custom compare function that can match any kind of data, there can be even a more complex data structure like a class instance of some kind of object you just define. Let's say a Person class
, that has a field age
and you want to sort all Persons by age.
And that's one example where you can use void *
, you can abstract this and create other use cases based on this example.
It is true that is a C example, but I think, being something that appeared in C can make more sense of the real usage of void *
. If you can understand what you can do with void *
you are good to go.
For C++ you can also check templates, templates can let you achieve a generic type for your functions / objects.
c++
we almost never needvoid*
. Templates largely get rid of places where we have an unknown type, typed runtime helpers such asstd::copy
get rid of places where we'd use CRT functions that havevoid*
parameters likememcpy
. Any new piece of C++ code which isn't deliberately interfacing with C or doing low level packing/manipulation which usesvoid*
should be viewed with suspicion. – Ryuntype
controls Pointer Arithmetic. Without a known type, thenptr++
andptr--
are meaningless and undefined. With achar*
pointer,ptr++
advances 1-byte to the next character, forint*
,ptr++
advances by 4-bytes to the next integer. With a class object, saymyclass*
,ptr++
will advancesizeof (myclass)
bytes to the nextmyclass
object. Withvoid*
nothing tells the compiler how big the pointed to object is. Now there are other ways thatvoid*
is usable, but this is the general reason why. – Invisiblesizeof(int)
, which often but not universally is 4. In the past you also saw 2. Anddouble
isn't a class either, but incrementing a double pointer also increments it bysizeof(double)
bytes. The rule is absolute. Even forchar*
, incrementing it will increment it bysizeof(char)
, its just thatsizeof(char)
is defined to be 1. – Kooima