目录
1. 函数指针
2. 函数指针数组
2.1函数指针数组的定义
2.2函数指针数组应用
3. 指向函数指针数组的指针
思维导图:
1. 函数指针
直接上代码:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);//取函数地址
return 0;
}
输出:
输出:
00F013CF
00F013CF
打印出来的其实就是函数的地址,
通过观察我们发现函数名的地址与&函数名其实是一样的。
那我们该如何存储函数的地址呢?
例:
#include <stdio.h>
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 <stdio.h>
//函数实现
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 <stdio.h>
//菜单打印
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;
}
写在最后:
以上就是本篇文章的内容了,感谢你的阅读。
如果喜欢本文的话,欢迎点赞和评论,写下你的见解。
如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。
之后我还会输出更多高质量内容,欢迎收看。