【C语言】深入理解指针(4)
目录
一、回调函数
1.什么是回调函数
2.回调函数举例
3.代码的回调流程
二、冒泡排序使用回调函数模拟实现qsort
1.冒泡排序的缺陷
2.qsort()函数的使用
代码的回调流程
3.模拟实现
char*类型的指针变量的妙用
代码的回调流程
4、补充:数据大小的比较
一、回调函数
1.什么是回调函数
回调函数就是一个通过函数指针调用的函数。
如果把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
2.回调函数举例
每一个case语句中虽然执行计算的逻辑 是区别的,但是输入输出操作是冗余的,
因为case语句中只有调用函数的逻辑有差异,并且实现具体计算的四个函数类型是一样的,所以我们可以把调用的函数的地址以参数的形式传递过去,使用函数指针接收,函数指针指向什么函数就调用什么函数,这里其实使用的就是回调函数的功能。
没有使用回调函数
使用回调函数
3.代码的回调流程
二、冒泡排序使用回调函数模拟实现qsort
qsort()本身不能确定需要排序何种类型的数据,但是提供了一个需要由使用者自己实现的进行大小比较的函数接口
int (*compar)(const void*, const void*)
void*的指针变量只能得到变量地址,不能得到变量的类型,无从得知一个元素有多大,所以不能进行解引用和运算,但是可以接收任意类型的指针变量,使用void*就是为了能接收任意变量类型,再根据自己需要进行强转
冒泡排序使用回调函数模拟实现qsort()也采用这样的思路,底层使用冒泡排序,具体是什么类型的比较需要使用者自己先写出来一个大小比较函数
1.冒泡排序的缺陷
冒泡排序:
一种排序算法,但是只能进行一种数据类型的排序(如果使用冒泡排序对字符串和结构体等元素进行排序,不能使用 > < 号)
void Bubble_sort(int* arr, int size) {int tmp = 0;//总共比较的趟数for (int i = 0; i < size - 1; i++){//下标为0的元素在每一趟中比较的次数for (int j = 0; j < size - 1 - i; j++){if (arr[j] > arr[j + 1]){tmp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = tmp;}}} }
2.qsort()函数的使用
qsort()是库函数中用于实现任意数据类型排序的函数
- 函数原型如下
- 比较函数的实现要求
- 因为qsort函数的设计者无法提前知道使用者需要进行何种类型的数据比较,所以留出来大小比较的函数由使用者自行设计
- void*不能解引用,也不能进行+-整数的操作,需要使用者根据需要自行进行类型强转
应用实例:
代码的回调流程
3.模拟实现
char*类型的指针变量的妙用
事先不知道会比较何种数据类型,
所以直接使用刚好只能操作一个字节地址的 char 类型指针
通过 char* 加上 size 可以模拟得到任意类型的指针变量循环size次的char*++可以访问任意类型变量的每个字节地址
//模仿 qsort 将冒泡排序改成使用回调函数实现任意类型的排序,自行实现(以比较整型为例) int compar(const void* p1, const void* p2) {return *(int*)p1 - *(int*)p2; }//事先不知道会比较何种数据类型 //直接使用刚好只能操作一个字节地址的 char 类型指针 //通过 char* 加上 size 可以模拟得到任意类型的指针变量 //循环 size 次的 char* ++ 可以访问任意类型变量的每个字节地址 void Swap(char* p1, char* p2, size_t size) {for (int i = 0; i < size; i++){char tmp = *p1;*p1 = *p2;*p2 = tmp;p1++;p2++;} }int Bubble_sort(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2)) {//总共比较次数for (int i = 0; i < num - 1; i++){//下标为0的元素在每一趟中比较的次数for (int j = 0; j < num - 1 - i; j++){//因为事先不知道比较的是何种数据类型//又因为 char类型的指针+1正好跳过一个字节//所以统一强转成 char* 指针变量,通过 size 跳过不同的距离,从而准确读取不同的数据if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0){Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}} }int main() {int arr[5] = { 5,3,4,1,2 };int num = sizeof(arr) / sizeof(arr[0]);Bubble_sort(arr, num, sizeof(arr[0]), compar);for (int i = 0; i < num; i++){printf("%d ", arr[i]);}return 0; }
代码的回调流程
4、补充:数据大小的比较
整型和浮点型可以使用><号进行比较
字符串使用库函数strcmp()进行比较,需加上头文件#include <string.h>
结构体的比较实际是某一个成员变量的比较