void pointers are very useful. Let's look at the standard library function malloc(). It needs to return a pointer to an appropriately aligned and containing the required amount of storage. One can call malloc() to allocate space for any type, including user defined types:
Code:
struct t {char *s;
};
...
struct t x;
...
x = malloc(sizeof *x);
So, what should be return type of malloc()? The answer is void *, because a void * can be assigned to any other pointer type without any loss of information. Another example is the function qsort(), which can be used to sort any type of variables in an array. For this, qsort() expects a function that can compare the types in question. Now, since the types can be anything, the function prototype is supplied as:
Code:
int(*compar)(const void *, const void *);
So, one could write a trivial function to sort an array of ints:
Code:
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void *a, const void *b);
int main(void)
{int a[] = { 1, 5, 2, 9, 3};
size_t n = sizeof a / sizeof a[0];
qsort(&a, n, sizeof a[0], cmp_int);
for (i=0; i < n; i++)printf("%d\n", a[i]);
return EXIT_SUCCESS;
}
int cmp_int(const void *a, const void *b)
{const int *f = a;
const int *s = b;
if (*f < *s) {return -1;
} else if (*f > *s) {return 1;
} else {return 0;
}
}
Note the first two assignment statements in cmp_int().
void * was not present in K&R C. In K&R C, one had to use char * to the same thing. I think even today using char * in place of void * is guaranteed to work by the standard, but I am not sure. In any case, using void * makes more sense anyway as it is less confusing.
HTH