A pointer to untyped data. You cannot perform pointer arithmetic on it (such as
++), as the associated data have no size. You cannot dereference it, as it doesn't point to any type. About the only thing you can do is cast it to another pointer type, and cast another (data) pointer type to it. Note that this doesn't apply to
void **, for which you can (and should) perform pointer arithmetic!
So what good is it?
It is guaranteed to be safe to cast another data (an earlier version of this writeup didn't have this word, and was wrong: you cannot safely cast a function pointer to
void * or back; this omission from the standard is strange) pointer type to
void * and then back again. The following is always legal and does what you'd expect:
/* ... make p point to a my_t ... */
q = p; /* (1) */
/* ... do stuff preserving q ... */
p = NULL;
/* ... more stuff preserving q ... */
p = q;
/* p now points to its value at (1) */
It's useful in various librari
es that need to keep pointers to generic
data, with the type of which they needn't concern themselves. For instance, a callback
is an application routine
called (through a function pointer
) in a library to perform actions on behalf of the application. Typically, the library wants to pass some parameters of its own to the callback, but the application also wants to pass a block of data. The solution? The application passes the library a function pointer and
a pointer to application data. The library can do nothing with the pointer to application data,
pass it to the callback.
What type can the application data pointer be? Well, the application typically want a pointer to some
struct containing the data. But the library cannot know about this struct (typically it may have been compiled before the application was even written!). The solution? The application passes the data pointer as a
void * parameter; the callback function, in the application, can implicitly cast this parameter back to the appropriate type. Some people call this an opaque data pointer: it's a pointer to data which the library cannot see.
Another example: the return type of
malloc() is a pointer value to a block that can hold any type. But how can we declare that? We can't; instead,
void *. The standard guarantees that this pointer may safely be cast to a pointer to any data type, so you can say
SomeType *t = malloc(sizeof *t);