这里有一个对于 C 语言中 qsort()
函数的经典讲解。遂记录之。
/**
* 《代码的未来》2.6 图3 关于 C 语言 qsort 使用的一种典型示例
*/
#include <stdio.h>
#include <stdlib.h>
int icmp(const void *a, const void *b)
{
int x = *(int*)a; // 先把 a 转成指向 int 型的指针,之后再把它的值给解出来
int y = *(int*)b;
if (x == y) return 0;
if (x > y) return -1;
return 1;
}
int main(int argc, char **argv)
{
int ary[] = {4, 7, 1, 2};
const size_t alen = sizeof(ary) / sizeof(int); // 这里是为了实现通用性 ① ②
size_t i;
// 排序前
for (i = 0; i < alen; i++) {
printf("ary[%d] = %d ", i, ary[i]);
}
printf("
");
qsort(ary, alen, sizeof(int), icmp); // ③
// 排序后,注意,这里的顺序是降序
for (i = 0; i < alen; i++) {
printf("ary[%d] = %d ", i, ary[i]);
}
}
输出:
ary[0] = 4 ary[1] = 7 ary[2] = 1 ary[3] = 2
ary[0] = 7 ary[1] = 4 ary[2] = 2 ary[3] = 1
① size_t
,在 CLion 中查看源码可以得到:
因为我的机器是 64 位系统,所以 size_t
是 unsigned long long
类型也就不足为奇。
贴一段《C Primer Plus》上关于 long long
类型的讲解:
现在,个人计算机上最常见的设置是,long long 占 64 位,long 占 32 位,short 占 16 位,int 占 16 位或 32 位(依计算机的自然字长而定)。原则上,这 4 种类型代表 4 种不同的大小,但是在实际使用中,有些类型之间通常有重叠。
C 标准对基本数据类型只规定了允许的最小大小。对于 16 位机,short 和 int 的最小取值范围是 [−32768,32767];对于 32 位机,long 的最小取值范围是 [−2147483648,2147483647]。对于 unsigned short 和 unsigned int,最小取值范围是 [0,65535];对于 unsigned long,最小取值范围是 [0,4294967295]。long long 类型是为了支持 64 位的需求,最小取值范围是 [−9223372036854775808,9223372036854775807];unsigned long long 的最小取值范围是 [0,18446744073709551615]。如果要开支票,这个数是一千八百亿亿六千七百四十四万亿零七百三十七亿零九百五十五万一千六百一十五。但是,谁会去数?
所以,用这个类型来记录 size
我想应该是很合适吧。毕竟范围这么广。
② 关于 sizeof
也有些淡忘,这是一个操作符,我们只需要理解它可以计算变量或者数据类型等所占的内存大小(字节)即可。
③ 最重要的,就是这个 qsort()
函数了。
我们先来看函数的声明:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
- 参数
base
,它的类型是void *
,这是为了方便给各种数据数组进行排序。 - 参数
nmembe
,元素数量。 - 参数
size
,待排序数据其类型的大小。 - 参数
compar
是指向一个带两个参数的函数的指针。代表了排序的规则。比如,上面的例子中,就是降序规则。
由此,实现了算法的通用化。