像那种代刷网站怎么做,企业营销型网站建设价格,校园网站建立,北京建设部官网#x1f3e0;个人主页#xff1a;黎雁 #x1f3ac;作者简介#xff1a;C/C/JAVA后端开发学习者 ❄️个人专栏#xff1a;C语言、数据结构#xff08;C语言#xff09;、EasyX、游戏、规划 ✨ 从来绝巘须孤往#xff0c;万里同尘即玉京 文章目录前景回顾#xff1a;前…个人主页黎雁作者简介C/C/JAVA后端开发学习者❄️个人专栏C语言、数据结构C语言、EasyX、游戏、规划✨ 从来绝巘须孤往万里同尘即玉京文章目录前景回顾前四篇指针核心速记 一、回调函数通过函数指针调用的函数 1. 回调函数的定义与理解2. 代码示例计算器中的回调函数3. 生活类比理解回调函数二、qsort函数通用排序的利器 ⚡1. qsort函数的原型2. 比较函数的规则3. qsort的使用案例案例1排序整型数组案例2排序结构体数组三、模拟实现qsort基于冒泡排序的通用改造 1. 核心改造思路2. 完整模拟实现代码写在最后 指针系列的倒数第二篇来啦这一篇我们将聚焦指针的终极实战用法——回调函数同时深度解析库函数qsort的使用方法和模拟实现帮你彻底掌握指针在通用算法中的灵活应用为下一篇的笔试面试题精讲做好充分准备前景回顾前四篇指针核心速记 指针第一讲从内存到运算吃透指针核心逻辑指针第二讲const 修饰、野指针规避与传址调用指针第三讲数组与指针深度绑定 二级指针 指针数组全解析指针第四讲字符指针、数组指针、函数指针及转移表应用想要吃透本篇的实战内容先回顾前四篇的关键知识点指针本质是地址不同类型的指针指向不同的目标对象包括变量、数组、函数。数组与指针深度绑定数组传参本质传递首元素地址函数指针可存储函数地址实现对函数的间接调用。函数指针数组可以构建转移表简化多分支逻辑typedef可重命名复杂的指针类型提升代码可读性。一、回调函数通过函数指针调用的函数 回调函数是C语言中一种重要的编程思想它的核心是把函数的地址作为参数传递给另一个函数在合适的时机通过函数指针调用这个函数。这一知识点也是笔面试中的高频考点。1. 回调函数的定义与理解回调函数不是由函数的实现者直接调用而是由其他函数通过函数指针间接调用。回调函数的出现让程序的逻辑分层更清晰也让功能的拓展更灵活。2. 代码示例计算器中的回调函数以简易计算器为例Add、Sub等功能函数就是回调函数它们的地址被传递给calc函数在calc函数中被调用。#includestdio.h// 功能函数——回调函数intAdd(intx,inty){returnxy;}intSub(intx,inty){returnx-y;}// 中间层函数接收函数指针调用回调函数voidcalc(int(*p)(int,int)){intx0,y0,r0;printf(请输入两个操作数);scanf(%d %d,x,y);rp(x,y);// 通过函数指针调用回调函数printf(计算结果%d\n,r);}// 菜单函数voidmenu(){printf(*************************\n);printf(*** 1.add 2.sub ***\n);printf(*** 0.exit ***\n);printf(*************************\n);}intmain(){intinput0;do{menu();printf(请选择);scanf(%d,input);switch(input){case1:calc(Add);// 传递Add函数地址break;case2:calc(Sub);// 传递Sub函数地址break;case0:printf(退出程序\n);break;default:printf(选择错误\n);break;}}while(input);return0;}3. 生活类比理解回调函数回调函数的逻辑就像酒店的叫醒服务用户主函数告诉前台中间层函数叫醒的时间和方式传递回调函数地址。到了指定时间前台中间层函数按照用户要求的方式调用回调函数叫醒用户。用户不需要自己定闹钟只需要提供“叫醒方式”前台负责执行。二、qsort函数通用排序的利器 ⚡qsort是C语言标准库中的排序函数基于快速排序算法实现可以排序任意类型的数组包括整型、字符型、结构体等其核心就是借助回调函数实现通用比较逻辑。qsort的使用与模拟实现是笔面试的重点考察内容。1. qsort函数的原型使用qsort需要包含头文件stdlib.h函数原型如下voidqsort(void*base,// 待排序数组的首元素地址size_tnum,// 待排序数组的元素个数size_tsize,// 数组中每个元素的大小单位字节int(*compar)(constvoid*,constvoid*)// 比较两个元素的回调函数);2. 比较函数的规则qsort的第四个参数是一个函数指针指向的比较函数需要遵循固定规则若p1指向的元素 p2指向的元素返回大于0的数。若p1指向的元素 p2指向的元素返回0。若p1指向的元素 p2指向的元素返回小于0的数。函数参数是const void*类型可接收任意类型的地址使用时需强制类型转换。3. qsort的使用案例案例1排序整型数组#includestdio.h#includestdlib.h// 整型比较函数升序intcmp_int(constvoid*p1,constvoid*p2){// void* 不能直接解引用需强制转换为int*return*(int*)p1-*(int*)p2;}// 整型比较函数降序// int cmp_int(const void* p1, const void* p2)// {// return *(int*)p2 - *(int*)p1;// }// 打印数组voidprint_arr(intarr[],intsz){inti0;for(i0;isz;i){printf(%d ,arr[i]);}printf(\n);}voidtest1(){intarr[]{9,7,5,3,1,2,4,6,8,0};intszsizeof(arr)/sizeof(arr[0]);qsort(arr,sz,sizeof(arr[0]),cmp_int);printf(排序后);print_arr(arr,sz);}intmain(){test1();return0;}案例2排序结构体数组按姓名或年龄排序结构体数组只需编写对应的比较函数。#includestdio.h#includestdlib.h#includestring.hstructStu{charname[20];intage;};// 按姓名比较字典序intcmp_stu_by_name(constvoid*p1,constvoid*p2){// 结构体指针访问成员用-returnstrcmp(((structStu*)p1)-name,((structStu*)p2)-name);}// 按年龄比较升序intcmp_stu_by_age(constvoid*p1,constvoid*p2){return((structStu*)p1)-age-((structStu*)p2)-age;}// 打印结构体数组voidprint_stu(structStuarr[],intsz){inti0;for(i0;isz;i){printf(姓名%s 年龄%d\n,arr[i].name,arr[i].age);}}voidtest2(){structStuarr[]{{zhangsan,20},{lisi,25},{wangwu,18}};intszsizeof(arr)/sizeof(arr[0]);// 按姓名排序qsort(arr,sz,sizeof(arr[0]),cmp_stu_by_name);printf(按姓名排序后\n);print_stu(arr,sz);// 按年龄排序// qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);// printf(按年龄排序后\n);// print_stu(arr, sz);}intmain(){test2();return0;}三、模拟实现qsort基于冒泡排序的通用改造 我们可以基于冒泡排序的思想结合回调函数模拟实现一个通用的qsort函数理解其底层逻辑。这一实现思路在笔面试中极容易被考察。1. 核心改造思路参数设计参考库函数qsort设计void* base、元素个数、元素大小、比较函数指针四个参数。元素比较借助比较函数指针调用用户提供的比较逻辑判断两个元素的大小。元素交换因为元素类型不确定需按字节交换设计一个通用的Swap函数。2. 完整模拟实现代码#includestdio.h#includestring.h// 通用交换函数按字节交换两个元素voidSwap(char*buf1,char*buf2,intwidth){inti0;for(i0;iwidth;i){chartmp*buf1;*buf1*buf2;*buf2tmp;buf1;buf2;}}// 模拟实现qsort基于冒泡排序voidbubble_sort(void*base,intsz,intwidth,int(*cmp)(constvoid*p1,constvoid*p2)){inti0;// 控制冒泡排序的趟数for(i0;isz-1;i){intflag1;// 标记是否已有序intj0;// 控制每一趟的比较次数for(j0;jsz-1-i;j){// 计算第j个和第j1个元素的地址// 强转为char*width就是跳过一个元素的字节数if(cmp((char*)basej*width,(char*)base(j1)*width)0){// 交换两个元素Swap((char*)basej*width,(char*)base(j1)*width,width);flag0;}}if(flag1){break;// 已有序提前结束}}}// 整型比较函数intcmp_int(constvoid*p1,constvoid*p2){return*(int*)p1-*(int*)p2;}// 打印数组voidprint_arr(intarr[],intsz){inti0;for(i0;isz;i){printf(%d ,arr[i]);}printf(\n);}voidtest(){intarr[]{9,7,5,3,1,2,4,6,8,0};intszsizeof(arr)/sizeof(arr[0]);bubble_sort(arr,sz,sizeof(arr[0]),cmp_int);printf(排序后);print_arr(arr,sz);}intmain(){test();return0;}写在最后 本篇内容聚焦指针在实战和算法中的核心应用回调函数与qsort的知识点紧密关联笔面试考点。掌握这些内容你就拥有了应对指针类编程题的重要基础。下一篇我们将直击指针经典笔试面试题从易到难拆解各类高频考题帮你理清解题思路轻松应对求职和考试中的指针难关