思维导图:
1. 函数指针
直接上代码:
#include void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test);//取函数地址 return 0; }
输出:
输出:
00F013CF
00F013CF
打印出来的其实就是函数的地址,
通过观察我们发现函数名的地址与&函数名其实是一样的。
那我们该如何存储函数的地址呢?
例:
#include void test() { printf("hehe\n"); } int main() { //*与指针名先结合,左边是函数返回类型,右边是函数传的参数 void (*pfun1)() = &test;//因为test与&test其实是一样的 //所以&是可以省略的 return 0; }
学到这里,我们读两段有趣的代码:
int main() { (*(void (*)())0)(); void (*signal(int, void(*)(int)))(int); return 0; } 他们分别代表着什么呢? int main() { (*(void (*)())0)(); //这是一段函数调用, //将0强制类型转换成一个类型是void (*)()的函数指针 //然后调用0地址处的函数 void (*signal(int, void(*)(int)))(int); //这是一段函数声明, //声明的是一个函数名是signal //返回类型是void(*)(int)类型的函数指针 //参数类型是int和void(*)(int)的一个函数 return 0; }
2. 函数指针数组
2.1函数指针数组的定义
函数指针数组是什么?
其实就是一个数组的每个元素都是函数指针。
例:
int main() { int (*parr1[10])(); //这就是一个函数指针数组,parr1与[10]先结合表面他是一个数组 //而他这个数组每个元素的类型是int(*)()的函数指针 return 0; }
2.2函数指针数组应用
函数指针究竟有什么用呢?
我们实现一个计算器试试:
一般的思路:
#include //函数实现 int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } //菜单打印 void menu() { printf("1.加法\n2.减法\n3.乘法\n4.除法\n0.退出\n"); } void test() { int input = 0; int x = 0, y = 0; int ret = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch(input) { case 1: printf("请输出:>"); scanf("%d %d", &x, &y); ret = Add(x, y); printf("%d\n", ret); break; case 2: printf("请输出:>"); scanf("%d %d", &x, &y); ret = Sub(x, y); printf("%d\n", ret); break; case 3: printf("请输出:>"); scanf("%d %d", &x, &y); ret = Mul(x, y); printf("%d\n", ret); break; case 4: printf("请输出:>"); scanf("%d %d", &x, &y); ret = Div(x, y); printf("%d\n", ret); break; case 0: printf("计算器已退出\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); } int main() { test();//分装函数实现 return 0; }
但是我们发现这样实现代码量太多,
或者说代码重复的部分太多,代码冗余,那我们该如何改进呢?
利用函数指针数组的思路:
#include //菜单打印 void menu() { printf("1.加法\n2.减法\n3.乘法\n4.除法\n0.退出\n"); } //函数实现 int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } //函数指针数组存放上述函数的地址 int (*pf[5])(int, int) = { NULL, Add, Sub, Mul, Div }; void test() { int input = 0; int x = 0; int y = 0; int ret = 0; do { menu(); printf("请选择:>"); scanf("%d", &input);//这里输入函数指针数组的下标 if (input == 0)//用if else语句判断退出和选择错误的特殊情况 { printf("退出计算器\n"); break; } else if (input >= 1 && input <= 4)//使用计算器的情况 { printf("请输入两个操作数:>"); scanf("%d %d", &x, &y); ret = pf[input](x, y);//通过函数指针数组调用函数 printf("%d\n", ret); } else { printf("选择错误\n"); } } while (input); } int main() { test();//分装函数实现 return 0; }
这样写,代码冗余的问题也解决了,
这就是函数指针数组的一个应用场景,
当然,函数指针数组也有一定的缺陷,比如实现这个计算器时:
想要通过数组访问,每个函数指针的参数必须要相同。
3. 指向函数指针数组的指针
我们学了函数指针,
又学了函数指针数组,
当然也有指向函数指针数组的指针啦!
例:
int Add(int x, int y) { return x + y; } int main() { int(*padd)(int, int) = Add; //这是一个函数指针 int(*parr[5])(int, int);//这是一个函数指针数组 int(*(*pparr)[5])(int, int) = &parr; //*与指针名先结合,证明这是一个指针,与[]相连证明这是一个数组指针, //而这个数组指针每个元素的类型是int(*)(int,int)的函数指针, //这就是一个指向函数指针数组的指针。 return 0; }
写在最后:
以上就是本篇文章的内容了,感谢你的阅读。
如果喜欢本文的话,欢迎点赞和评论,写下你的见解。
如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。