函数指针,顾名思义,就一个指向函数的指针.
那么
整形指针是接收整形的地址;
字符指针是接收字符的地址.
数组指针是接收数组的地址
函数有地址吗?函数名又可以代表什么?
示例:自定义一个加法函数,观察函数的地址
//函数指针 #includeint add(int a,int b)//自定义一个加法函数 { return a + b; } int main() { int a = 2, b = 3; int c=add(a, b); printf("%d\n", c);//确认一下函数是否正确 printf("%p\n", &add);//取出函数的地址 printf("%p\n", add);//用数组名打印 return 0; }
运行结果:(在不同环境下地址会不一样,这里采用的是vs x86环境)
5
00E61023
00E61023
不难发现,函数名也可以代表函数的地址.
那么函数指针该怎么写呢?
以数组指针为例:
数组指针示例:写一个指向 int arr[10] 数组的数组指针;
第一步: (*p) //先确定是一个指针 第二步: (*p)[10] //确定指向的是一个有10个元素的数组 第三步: int(*p)[10] //确定该数组元素为int型 第四步: int(*p)[10]=&arr;//将数组的地址赋值给数组指针 //或者int(*p)[10]=arr;
示例2:
函数指针:指向int add(int a,int b)
第一步: (*p) //先确定是一个指针 第二步: (*p)(int,int) //确定指向的函数有两个参数 第三步: int (*p)(int,int) //确定该函数的返回类型 第四步: int (*p)(int,int)=&add;//将函数的地址赋值给函数指针 //等价于:int (*p)(int,int)=add;
那么函数指针有什么用吗?
当然是用来调用函数了.
同样以数组指针为例:
使用数组指针访问数组.
int main() { int arr[10] = { 1,2,3,4,5 }; int(*p)[10] = arr; for (int i = 0; i < 5; i++) { printf("%d ", ( * p)[i]); } printf("\n"); return 0; }
使用函数指针调用函数
#includeint add(int a,int b) { return a + b; } int main() { int a = 2, b = 3; int(*p1)(int, int) = &add; int(*p2)(int, int) = add; int ret1=add(a,b); int ret2=(*p1)(a, b);//写法一 int ret3=p1(a, b);//写法2 printf("ret1=%d\nret2=%d\nret3=%d",ret1,ret2,ret3); return 0; }
运行结果:都能完成函数的调用
ret1=5
ret2=5
ret3=5
函数指针数组实质用于存放函数指针的数组.
即数组的成员都是函数指针.
写法:以数组成员都是指向类似int add(int,int)的函数指针为例
1.先写出函数指针 (int) (*p)(int,int) 2.改成数组 (int) (*p[10])(int,int)//函数指针数组
题目:使用c语言制作简单的计算器.
要求,可以进行加减乘除运算.
//简易计算器 #includevoid menu()//菜单 { printf("作者:初阶牛\n"); printf(" 欢迎使用计算器:\n"); printf("+-------------------------------+\n"); printf("| 1.add 2.sub |\n"); printf("| 3.mul 4.div |\n"); printf("| 0.退出 |\n"); printf("+-------------------------------+\n"); } 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=0, y=0; int input = 1; int ret = 0; do { menu();//打印菜单 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; }
对于上面的代码,我们可以使用函数指针来简化.
感受一下函数的指针的魅力吧!
#includevoid menu() { printf("作者:初阶牛\n"); printf(" 欢迎使用计算器:\n"); printf("+-------------------------------+\n"); printf("| 1.add 2.sub |\n"); printf("| 3.mul 4.div |\n"); printf("| 0.退出 |\n"); printf("+-------------------------------+\n"); } 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 = 0, y = 0; int input = 1; int ret = 0; int(*arr[5])(int, int)={0,add,sub,mul,div};//使用函数指针数组 do { menu(); scanf("%d", &input); if (input > 0 && input < 5) { printf("输入两个操作数:"); scanf("%d %d", &x, &y); ret=arr[input](x,y);//利用数组下标调用相应的函数 printf("ret = %d\n", ret); } else if (input == 0) { printf("退出计算器\n"); break; } else { printf("很遗憾,并没有这个选项:\n"); break; } } while (input); return 0; }
函数指针数组指针:
指向一个数组.该数组的成员都是函数指针.
写法:
1.先写出函数指针 char* (*p)(const int, double, char*); 2.改成函数指针数组 char* (*pp[3])(const int, double, char*); 3.最后写成函数指针数组指针 char* (*(*ppp)[3])(const int, double, char*);
可以通过函数指针p调用函数,
也可以通过函数指针数组的元素,pp[0]调用函数.
最后,可以通过(*ppp)找到函数指针数组,(*ppp)[0]调用函数.
示例:
char* test(const int a, double b, char* c) { char* ret = "AAABBBCCCDDD\n"; return ret; } #includeint main() { //函数指针 char* (*p)(const int, double, char*)=test; //函数指针数组 char* (*pp[3])(const int, double, char*); pp[0] = test; //函数指针数组指针 char* (*(*ppp)[3])(const int, double, char*)=&pp; printf("%s", test(0,0,0)); printf("%s", p(0, 0, 0)); printf("%s", pp[0](0, 0, 0)); printf("%s", (*ppp)[0](0, 0, 0)); return; }
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
大家还记得冒泡排序吗?
但是冒泡排序只能排序整形,而qsort函数,内部采用快速排序,可以排序各种类型的数据,接下来展示qsort排序部分类型的方法.
示例:qsort函数部分应用
分别将元素比较方法int_cmp和char_cmp的指针(地址) 传给 qsot函数.由qsort函数调用这些比较函数.
#include#includeint int_cmp(void* e1, void* e2)//整形元素排序方法 { return *(int*)e1 - *(int*)e2; } int char_cmp(void* e1, void* e2)//字符型元素排序方法 { return (*(char*)e1) - (*(char*)e2); } int main() { int arr1[10] = { 4,5,1,8,9,2,10,3,7,6 }; char arr2[] = "fbadegc"; int sz1 = sizeof(arr1) / sizeof(arr1[0]); int sz2 = sizeof(arr2) / sizeof(arr2[0]); qsort(arr1,sz1,sizeof(arr1[0]),int_cmp); for (int i=0; i < sz1; i++) { printf("%d ", arr1[i]); } printf("\n"); qsort(arr2, sz2, sizeof(arr2[0]), char_cmp); for (int i = 0; i < sz2; i++) { printf("%c ", arr2[i]); } printf("%s", arr2); return 0; }
运行结果:
1 2 3 4 5 6 7 8 9 10
a b c d e f g
Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者