C语言-函数指针

📅 2026/7/31 4:47:25
C语言-函数指针
回顾数组指针本质是指向数组首地址的指针操作一维、二维数组均只需要知道数组首元素即可二维数组就是一维数组的嵌套实际上为基类型的数组。通过指针访问二维数组中的数据pi //第i行的地址 p是的数据类型 int(*)[4] *(pi) //切换 到第2维 *p三步运算 *(pi) 代表就是一个int[4]的数组 *(pi)就是第i行 的数组名 *(pi) j //第2维 对应的 数组 地址 偏移到 第j个元素 *(*(pi) j) //第2维 对应的 第j个元素pi //行地址 *(pi) //行地址 转换为列地址 *(pi) j //列地址 进行偏移 *(*(pi)j) //访问第i行第j列的元素字符型指针数组char *s[] {hello,world,china};数组修饰符基类型为char *型因此数组内存储的是三个char *类型的元素分别指向三个字符串常量区的地址对应着三个常量字符串。二级指针如果要存放的是一个一级指针变量的地址就需要使用二级指针指向一级指针char *s hello; char **p s; char** *r p;一级指针如果要存放的是一个普通变量的地址直接使用一级指针即可int a 10; int * p a;练习选择排序定义一维字符型指针数组对指针数组内指针指向的字符串进行排序void select_point_twoArraystr(char **a,int len) { int i0; while(ilen-1) { int j i1; while(jlen) { if(strcmp(*(ai),*(aj))0) { char * temp *(ai); *(ai) *(aj); *(aj) temp; } j; } i; } }由于排序的是指针指向的内容因此需要使用二级指针来指向一级指针。依次遍历从指针数组内的指针指向的字符串的大小外循环控制当前比较的第几个指针元素指向的字符串内循环控制与后面每一个指针指向的字符串进行比较。每比较一次循环变量自增与后面的指针指向的字符串继续比较。循环完一轮后外循环变量自增排序好的元素指针向后偏移一个。练习字符型号指针数组进行排序后继续二分查找void find_point(char **a,char *b,int len) { char **begin a; char **end alen-1; char **mid begin (end-begin)/2; while(begin end) { mid begin (end-begin)/2; if(strcmp(*mid,b)0) { end mid - 1; }else if(strcmp(*mid,b)0) { begin mid 1; }else { printf(find yes\n); return ; } } printf(not found\n); }同样使用二级指针接收进行二分查找的指针数组的地址定义起始地址指针begin指向指针数组的首地址结束地址指针指向指针数组的末地址。计算中间指针进入循环。循环内重新求取中点用 strcmp 对比中点字符串与目标串若中点字符串字典序更大就把左区间右边界前移更小就把右区间左边界后移相等则提示找到并直接返回。当 begin 超过 end 时循环终止说明遍历完所有区间都未匹配输出查找失败。指针函数函数名就是函数的入口地址 一个函数它的返回值是指针char * strcpy()char * strcat()函数指针主体为指针变量int (*fun)(int x);括号的优先级最高因此结合之后fun为函数指针类型指向返回值类型为int型传入一个参数且参数为int型的这类型这类函数。函数的指针 目的是 希望通过指针的方式使用到函数回调函数把一个函数 A 的地址作为参数传给另一个函数 B由函数 B 在内部去调用函数 AA 就叫回调函数。本质依托函数指针实现。练习以回调函数实现输入两个数字和运算符进行加减乘除然后输出结果。int sum(int a,int b) { return ab; } int sub(int a,int b) { return a-b; } int mux(int a,int b) { return a*b; } int div1(int a,int b) { return a/b; } int div2(int a,int b) { return a%b; } void processData(int a,int b,int (*pfunc)(int,int)) { printf(result %d\n,pfunc(a,b)); } int main(int argc, const char *argv[]) { int a,b; char c; int (*p1)(int ,int) sum; int (*p2)(int ,int) sub; int (*p3)(int ,int) mux; int (*p4)(int ,int) div1; int (*p5)(int ,int) div2; printf(input tow num and operator:); scanf(%d%c%d,a,c,b); switch(c) { case : processData(a,b,p1); break; case -: processData(a,b,p2); break; case *: processData(a,b,p3); break; case /: processData(a,b,p4); break; case %: processData(a,b,p5); break; }首先定义加减乘除取余五个双目运算函数通过函数指针变量分别指向这些运算接口再封装 processData 统一调用函数指针执行运算并打印结果在主函数接收用户输入的两个整数与运算符利用 switch 匹配符号传递对应运算函数指针完成简易计算器四则及取余计算。编写系统快速排序中的回调函数void qsort( void *base, //要排序的数组的起始地址 size_t nmemb, //要排序的数组的元素个数 size_t size, //数组中单个元素的大小 int (*compar)(const void *, const void *) //回调函数的指针 compare --- 用来指定数组元素比较的规则 );#includestdio.h #includestdlib.h #includestring.h int compar(const void* a,const void* b) { const int *p a; const int *q b; return *p - *q; } int compar_str(const void* a,const void* b) { const char *p a; const char *q b; return strcmp(p,q); } int (*q) (const void *,const void *) compar_str; int main(int argc, const char *argv[]) { int a[] {6,5,4,3,2,1,9,8,10,7}; char b[][10] {F,W,O,E,C}; int len 5; qsort(b,len,10*sizeof(char),q); for(int i0;ilen;i) { printf(%s\n,b[i]); } putchar(\n); return 0; }void *类型指针void *空类型指针可以接收任意类型变量的地址不能直接解引用、不能做指针偏移运算必须强制转换成具体类型指针后才能操作。主要用于实现泛型回调函数的底层基础使用空指针接收后在进行强制类型转换从而实现回调函数对多种功能的支持。首先编写两个回调比较函数compar用于整型数值大小相减返回差值满足整数升序排序规则compar_str通过strcmp字符串库函数完成字符串字典序比对随后定义函数指针变量 q 指向字符串比较回调函数在主函数中分别准备 int 一维数组、二维字符字符串数组调用qsort对字符串数组传入元素个数、单个元素占用字节长度与自定义比较函数指针由库函数内部通过回调指针反复调用比对逻辑完成排序最后循环遍历打印排序后的字符串数组本质是利用函数指针把排序算法框架和元素比较规则解耦一套 qsort 接口可适配整数、字符串等不同类型数据的排序需求。堆区空间的使用堆是操作系统管理、程序员手动申请手动释放的内存空间栈由编译器自动分配释放堆完全靠代码控制生命周期从malloc申请开始直到free释放程序结束才回收。void *malloc(size_t size);功能申请size 字节未初始化堆内存内容随机垃圾值返回成功返回堆起始地址void*失败返回 NULL// 申请10个int空间 int *p malloc(10 * sizeof(int)); if (p NULL) { perror(malloc fail); return -1; }空间释放归还堆内存给操作系统避免内存泄漏同一块堆不能多次 free双重释放崩溃free 后指针变成野指针最好立刻置 NULL传入参数就是malloc申请的内存地址入口指针void free(void *ptr);注意1. free释放 一般 建议将对应指针设置NULL //free(p)之后此时p 悬空指针 (原型指向有效空间但是后来空间释放了变的无效但是p仍然指向这块空间)2. 如果只malloc但是没有free此时会发生内存泄露 //内存泄露 --- 使用了空间但是没有释放导致一直被占用3. 告诉操作系统这块空间用完了你可以拿回去自由分配4. malloc和free要成对出现5. malloc申请到的空间 是一片连续空间6. 不要多次free同一块空间7. 注意:指针函数中不能返回局部变量(auto这种局部变量-空间开在栈上的)的地址练习定义一个整型数组空间在堆上并输入数字最后进行求和输出main函数的参数:int main(int argc, const char* *argv)argc -- 表示命令行参数的个数argv -- 表示命令行参数的 指针数组 命令行参数 起始都是 字符串 以NULL作为结尾的数组