What does void* mean and how to use it?
Using a void * means that the function can take a pointer that doesn't need to be a specific type. For example, in socket functions, you have
send(void * pData, int nLength)
this means you can call it in many ways, for example
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));
C is remarkable in this regard. One can say void
is nothingness void*
is everything (can be everything).
It's just this tiny *
which makes the difference.
Rene has pointed it out. A void *
is a Pointer to some location. What there is how to "interpret" is left to the user.
It's the only way to have opaque types in C. Very prominent examples can be found e.g in glib or general data structure libraries. It's treated very detailed in "C Interfaces and implementations".
I suggest you read the complete chapter and try to understand the concept of a pointer to "get it".
A pointer to void
is a "generic" pointer type. A void *
can be converted to any other pointer type without an explicit cast. You cannot dereference a void *
or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.
void *
is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort
:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
is the address of an array, nmemb
is the number of elements in the array, size
is the size of each element, and compar
is a pointer to a function that compares two elements of the array. It gets called like so:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
The array expressions iArr
, dArr
, and lArr
are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int
/double
/long
" to "pointer to void
".
The comparison functions would look something like:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
By accepting void *
, qsort
can work with arrays of any type.
The disadvantage of using void *
is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
is expecting its arguments to be pointing to int
s, but is actually working with double
s. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.