C Language Pointers Polymorphic behaviour with void pointers


Example

The qsort() standard library function is a good example of how one can use void pointers to make a single function operate on a large variety of different types.

void qsort (
    void *base,                                 /* Array to be sorted */
    size_t num,                                 /* Number of elements in array */
    size_t size,                                /* Size in bytes of each element */
    int (*compar)(const void *, const void *)); /* Comparison function for two elements */

The array to be sorted is passed as a void pointer, so an array of any type of element can be operated on. The next two arguments tell qsort() how many elements it should expect in the array, and how large, in bytes, each element is.

The last argument is a function pointer to a comparison function which itself takes two void pointers. By making the caller provide this function, qsort() can effectively sort elements of any type.

Here's an example of such a comparison function, for comparing floats. Note that any comparison function passed to qsort() needs to have this type signature. The way it is made polymorphic is by casting the void pointer arguments to pointers of the type of element we wish to compare.

int compare_floats(const void *a, const void *b)
{
    float fa = *((float *)a);
    float fb = *((float *)b);
    if (fa < fb)
        return -1;
    if (fa > fb)
        return 1;
    return 0;
}

Since we know that qsort will use this function to compare floats, we cast the void pointer arguments back to float pointers before dereferencing them.

Now, the usage of the polymorphic function qsort on an array "array" with length "len" is very simple:

qsort(array, len, sizeof(array[0]), compare_floats);