void 指针的多态行为

qsort() 标准库函数是一个如何使用空指针,以使一个单一的功能上大量各种不同类型的工作一个很好的例子。

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 */

要排序的数组作为 void 指针传递,因此可以操作任何类型元素的数组。接下来的两个参数告诉 qsort() 它应该在数组中预期有多少元素,以及每个元素的大小(以字节为单位)。

最后一个参数是一个指向比较函数的函数指针,该函数本身带有两个 void 指针。通过使调用者提供此功能,qsort() 可以有效地对任何类型的元素进行排序。

这是比较浮点数的比较函数的一个例子。请注意,传递给 qsort() 的任何比较函数都需要具有此类型签名。它的多态性方式是将 void 指针参数转换为我们希望比较的元素类型的指针。

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;
}

由于我们知道 qsort 将使用此函数来比较浮点数,因此我们在解除引用它们之前将 void 指针参数转换回浮点指针。

现在,在长度为 len 的数组 array 上使用多态函数 qsort 非常简单:

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