深入理解指针(五)1.回调函数是什么回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针地址作为参数传递给另⼀个函数当这个指针被⽤来调⽤其所指向的函数时被调用的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的⽤于对该事件或条件进⾏响应。在深入理解指针四**(可以移步主页)**中我们写的计算机的实现的代码中红⾊框中的代码是重复出现的其中虽然执⾏计算的逻辑 是区别的但是输⼊输出操作是冗余的有没有办法简化⼀些呢可以将相似代码抽象成函数因为红⾊框中的代码只有调⽤函数的逻辑是有差异的我们可以把调⽤的函数的地址以参数的形式 传递过去使⽤函数指针接收函数指针指向什么函数就调⽤什么函数这⾥其实使⽤的就是回调函 数的功能。有了函数指针后函数的调用可以使用函数名调用也可以使用函数指针来调用代码语言javascriptAI代码解释//使⽤回调函数改造前 #include stdio.h int add(int a, int b) { return a b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { int x, y; int input 1; int ret 0; do { printf(*************************\n); printf( 1:add 2:sub \n); printf( 3:mul 4:div \n); printf(*************************\n); printf(请选择); scanf(%d, input); switch (input) { case 1: printf(输⼊操作数); scanf(%d %d, x, y); ret add(x, y); printf(ret %d\n, ret); break; case 2: printf(输⼊操作数); scanf(%d %d, x, y); ret sub(x, y); printf(ret %d\n, ret); break; case 3: printf(输⼊操作数); scanf(%d %d, x, y); ret mul(x, y); printf(ret %d\n, ret); break; case 4: printf(输⼊操作数); scanf(%d %d, x, y); ret div(x, y); printf(ret %d\n, ret); break; case 0: printf(退出程序\n); break; default: printf(选择错误\n); break; } } while (input); return 0; }代码语言javascriptAI代码解释//使⽤回调函数改造后 #include stdio.h int add(int a, int b) { return a b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } void calc(int(*pf)(int, int)) { int ret 0; int x, y; printf(输⼊操作数); scanf(%d %d, x, y); ret pf(x, y); printf(ret %d\n, ret); } int main() { int input 1; do { printf(*************************\n); printf( 1:add 2:sub \n); printf( 3:mul 4:div \n); printf(*************************\n); printf(请选择); scanf(%d, input); switch (input) { case 1: calc(add); break; case 2: calc(sub); break; case 3: calc(mul); break; case 4: calc(div); break; case 0: printf(退出程序\n); break; default: printf(选择错误\n); break; } } while (input); return 0; }2.qsort使用举例2.1 使用qsort函数排序整型数据qsort是库函数可以排序任意类型的数据底层使用的是快速排序的方式(头文件为(stdlib.h)在这里插入图片描述下边对qsort个参数进行解释代码语言javascriptAI代码解释void qsort(void* base,//指针指向的是待排序的数组的第一个元素 size_t num,//base指向的待排序数组的元素的个数 size_t size,//base指向待排序数组元素的大小 int(*compar)(const void*, const void*)//函数指针 );qosrt 函数有实现者qosrt 函数的使用者 —-明确的知道要排序的是什么数据这些数据应该如何比较所以提供两个元素的比较函数在深入理解指针三中,我们提到了冒泡排序代码如下代码语言javascriptAI代码解释#includestdio.h void bubble_sort(int arr[], int sz) { int i 0; for (i 0; i sz - 1; i) { int j 0; for (j 0; j sz - 1 - i; j) { if (arr[j] arr[j 1]) { int tmp arr[j 1]; arr[j 1] arr[j]; arr[j] tmp; } } } } void print_arr(int arr[], int sz)//参数写成数组的形式本质上还是指针 //形参的数组是不会再单独创建数组空间的所以形参的数组是可以省略掉数组大小不写的 { int i 0; for (i 0; i sz; i) { printf(%d , arr[i]); } } int main() { int arr[] { 9,8,7,6,5,4,3,2,1 }; //排为升序 int sz sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz); print_arr(arr, sz); }很容易发现该代码只适用于整数那么在使用冒泡排序的情况下要改造函数让它能够排序任意类型的数据该如何做到问题的主要原因是两个整型元素可以直接用比较但是两个字符串、两个结构体是不能用比较的参数以及数据的交换也需要更改我们可以把两个元素的比较封装成函数然后把函数地址传给排序函数代码语言javascriptAI代码解释#include stdio.h //qosrt函数的使⽤者得实现⼀个⽐较函数 int int_cmp(const void* p1, const void* p2) { //强制类型转换 if(*(int *)p1*(int *)p2)//此处不能写成if(*p1*p2) 因为void*类型的指针是无具体类型的指针这种类型的指针不能直接解引用也不能-整数运算 return 1; else if(*(int *)p1*(int *)p2) return 0; else return -1; } int main() { int arr[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i 0; qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); for (i 0; i sizeof(arr) / sizeof(arr[0]); i) { printf(%d , arr[i]); } printf(\n); return 0; }强调void*类型的指针是无具体类型的指针这种类型的指针不能直接解引用也不能±整数运算最后我们对代码做一下简化代码语言javascriptAI代码解释int int_cmp(const void* p1, const void* p2) { return (*(int*)p1 - *(int*)p2); } int main() { int arr[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i 0; qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); for (i 0; i sizeof(arr) / sizeof(arr[0]); i) { printf(%d , arr[i]); } printf(\n); return 0; }2.2 使用qsort排序结构数据这⾥需要补充介绍结构指针和结构体成员访问操作符 -;代码语言javascriptAI代码解释结构体变量.成员名 结构体指针-成员名结构体补充:代码语言javascriptAI代码解释struct Stu//学生 { char mane[20];//名字 int age;//年龄 }; int main() { struct Stu s{zhangsan,18}; printf(%s %d,s.name,s.age); return 0; }代码语言javascriptAI代码解释void print(struct Stu* ps) { //printf(%s %d,(*ps).name,(*ps).age); //可以但是啰嗦 printf(%s %d,ps-name,ps-age);//这两者等价 } struct Stu//学生 { char mane[20];//名字 int age;//年龄 }; int main() { struct Stu s{zhangsan,18}; print(s); return 0; }这两个结构体怎么比1.按照名字比较————-字符串比较—–strcmp头文件为string.h2.按照年龄比较————-整型比较那strcmp函数是怎么比较字符串大小的呢