The void
type in general means that no type information is given.
You should always keep in mind that a pointer conveys two pieces of information: the type of the pointed data (int
, double
, ...), which specifies how to interpret it, and the address of the data it points to, which specifies where you can get the actual value of the pointed data.
The type information is in the type of the pointer (double
*
, int
*
, ...), while the address of the data is the actual value contained in the pointer variable.
So, a void
pointer (void *
) is a pointer that do not specify any type information. It tells you where the data is, but it doesn't tell you how to interpret it. You know that at that address there's something, but you don't know if it's an int
, a double
or an array of flying cows. To actually use such data, you have to get type information about it in some other way (e.g. with some other magic parameter), cast that pointer to a regular pointer type and then use it as usual.
void *
is often used in C to provide some kind of support to generic programming; see for example the qsort
C library function.
A NULL
pointer, instead, is a pointer that points to nothing. In this case, the type information about the pointer in general is present, but it's the address of the pointed data that is missing. Of course, it's possible to have a void *
that is NULL
.
Quick example (supposing that v
is declared as double v;
):
Type information present
+----------------------+----------------------+
| ✔ | ✘ |
+---+----------------------+----------------------+
p c | | | |
v o o | ✔ | double * ptr = &v; | void * ptr = &v; |
a i n | | | |
l n t +---+----------------------+----------------------+
i t e | | | |
d e n | ✘ | double * ptr = NULL; | void * ptr = NULL; |
d t | | | |
+---+----------------------+----------------------+
Trivia: NULL
, at least in the current standard, is guaranteed to be 0.
In other areas of the language, void
is always used to specify lack of type. Using it as return value (note: I'm talking now about void
, not void *
) means that the function does not return any value, and casting an expression to void is a fancy way to discard a value (you're signaling to the compiler and to other programmers that you're conscious that you're not using a certain value).