1、函数指针数组
A、什么是函数指针数组
函数指针数组,是数组,存储的数据类型是函数指针。
我们可以看到,变量pf_arr就是一个函数指针数组,其中存储了四个函数,确切来说是四个函数指针,即四个函数的地址。
B、函数指针数组的使用
函数指针数组的使用很简单,就正常进行数组访问,拿到目标函数后,正常调用目标函数即可
如上图所示,最终我们可以得到两数相加、相减、相乘以及相除后的结果。
2、回调函数
A、什么是回调函数
回调函数:以函数指针为参数,并在函数内部调用该函数指针指向的函数,这样的一个函数,我们称之为回调函数。
由此,我们可以得到回调函数的两个关键特征:
1、以函数指针为参数
2、在函数内部调用了该函数指针指向的函数
B、qsort函数
qsort函数就是一个回调函数,就功能而言,是以快速排序思想实现的排序函数。
接下来,我们来讲一讲如何通过qsort函数实现冒泡排序。
a、理解void*类型
void* 是无类型的指针,也就是说任何类型的地址都可以赋值给void*类型的指针变量
不过也正因为void*是无类型的指针,所以void*类型的指针变量有两点限制:
1、不能进行解引用操作。因为指针指向的类型是无,所以无法确定访问几个字节,即访问权限不定
2、不能进行加减整数操作。同样是因为指针指向的类型是无,故地址移动时的步长不能确定
由此可见,要想使用void*类型的指针变量,必须得对该变量进行强制类型转换:
b、理解qsort函数
这是MSDN上关于qsort函数的参数定义:
这里比较复杂,我们可以对其略微进行简化:
我们对其中的四个参数分别进行解释:
1、void* base。base中存放的是要排序的那组数据的起始地址
2、size_t num。size_t 其实就是 unsigned int ,num中存放的是要排序的数据的个数
3、size_t width。width中存放的是要排序的数据在内存中所占的大小,单位是字节
4、int (*cmp) (const void* e1,const void* e2) 。cmp是变量名,是一个函数指针,指向的函数返回值类型为int,两个参数类型均为const void*,是两个void* 类型的指针变量
这个被指向的函数还有一些特别规定,它的返回值要满足如下条件:
注:上图中的elem1和elem2均指强制类型转换并解引用后相应得到的值
c、通过qsort函数实现冒泡排序
首先,使用qsort函数之前,要包含相应的头文件:<stdlib.h>
接下来是qsort函数的具体使用,这也是回调函数使用的一个典例:
我们可以看到,最终的输出结果为升序,可见qsort函数成功实现了升序冒泡排序。
当然,我们还可以对cmp函数实现的代码进行优化:
这样,代码就优化得极为简洁
通过上述案例我们可以发现,qsort函数默认实现的是升序排序,而要想实现降序排序,进行相应的颠倒即可。
比如说,将相减的顺序调换:
如此,我们便可得到降序输出的结果: