了解qsort()函数

int compare (const void * a, const void * b) { return ( (int) (*(float*)a - *(float*)b) ); } 

当我想使用qsort函数时,我应该按照我的理解以这种forms编写一个比较函数。 那么,为什么我们在比较函数的参数之前使用void呢?

并且,这是比较function标准及其参数和花括号中的代码,还是我们可以通过我们的愿望简单地更改代码甚至参数?

不,您无法更改参数或返回类型。 但是当然你可以改变function的’代码’。 你可以比较你想要的任何东西。 唯一重要的是返回值:

取自这里 :

如果第一个传递参数比第二个传递参数“低”,则返回值应<0 == 0如果两者都是identic则返回== 0 ,如果第一个传递参数为“更大”,则返回>0

例如,您可以使用带有这样的字符串的qsort函数:

 int compare (const void * a, const void * b) { return strcmp((char *) a, (char *) b); } 

在C void *意味着您可以在其中存储任何类型的指针。 想象一下,你想要对字符串列表(char *)进行排序,你会做什么? 为int数据类型编写一个qsort实现,为char *编写一个实现? 这里, qsort是使用void *编写的,允许您比较不同类型的不同东西。

是的,参数类型是标准的。 请参阅stdlib.h的定义。

 void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 

使用void指针的原因是因为它们可以转换为其他指针类型,然后返回到void指针而不会出现任何问题。

qsort正在使用一个允许你使用任意数据类型的callback ,然后在比较器中你可以任意方式对它们进行排序。 您只需要遵守API。

这提供了很大的灵活性。 下面的代码是一个简化的示例,但它可以扩展为轻松地对任意数据结构进行排序。 在所有情况下,使用相同的qsort函数,即调用相同地址的相同函数。

以下人为的例子可能有助于理解它的灵活性。 注意,比较器func_table可以扩展为结构表,而不是int ,而每个结构都有一个比较器类型。 重申一下,在每种情况下都会调用相同的qsort函数,它的回调函数地址会改变为在运行时对数据进行排序所需的正确函数。

以下程序按随机方向对数组进行排序,其中从表中选择sort函数。

 #include  #include  #include  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) int values[] = { 3 , 88 , 52 , 285, 63 , 288 , 576 , 10, 21 , 5,343 , 38 , 55 , 100, 552 , 85 }; typedef int (*comparator)(const void * a, const void * b); int cmp_reverse(const void * a, const void * b) { return ( *(int*)b - *(int*)a ); } int cmp_int(const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } static comparator func_table[2]; int main(void) { srand(time(NULL)); size_t int_arr_size = ARRAY_SIZE(values); int n = 0; int i = 0; func_table[0] = cmp_int; func_table[1] = cmp_reverse; while(i++ < 10) { int order = rand() % 2 == 0; printf("order: %d %s ", order, order == 0 ? ">" : "<"); qsort(values, int_arr_size, sizeof(int), func_table[order]); for( n = 0 ; n < int_arr_size; n++ ) { printf("%d ", values[n]); } printf("<\n"); } return 0; }