一、函数指针的声明和调用
1.指针声明:
函数指针顾名思义就是一个指向函数的指针。
int Add(int x,int y)
{
return x+y;
}
char* Sub(char*)
{
}
//声明函数指针并初始化
int (*Add)(int ,int ) ptr=&Add;
char* (*Sub)(char*) prt_char=⋐
这里声明了两个函数指针 ptr和ptr_char指向了函数的地址,这里会发现Add取地址(&ADD),同样是原类型加上一个*,就是 int(*Add)(int,int),注意不是int *Add(int,int)。
对于一个返回指针的函数来说也是一样,Sub取地址(&Sub)原类型加上一个*,就是char*(*Sub)(char*),注意不是char* *Sub(int,int);
PS:声明的指针的时候,函数的返回值和参数类型、个数都要对的上。
对于函数来说取地址Add (&Add),和直接写上本身是一样的(Add)。
所以初始化的时候也可以写成
int Add(int x,int y)
{
return x+y;
}
int (*Add)(int,int)pf=Add;
这种写法和上面等价。
2.指针函数的调用:
可以通过使用函数指针调用函数。
int Add(int x,int y){
return x+y;
}
int (*pf)(int,int)=&Add;
int ret=(*pf)(2,3); //等价于int ret=Add(2,3);
printf("%d\n",ret);
这里用指针调用函数的结果,跟直接使用函数的结果是一样的。
因为上面&Add和Add的地址是一样的,所以这里导致了,不管解引用了几次pf,得到的结果都是函数Add。
二、函数指针数组
就一个数组,里面存储的类型是,指向函数的指针。
声明:
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 (*pf1)(int,int)=Add; //声明初始化函数指针
int (*pf2)(int,int)=Sub;
int (*pf3)(int,int)=Mul;
int (*pf4)(int,int)=Div;
//函数指针数组
int (*pf[4])(int,int)={Add,Sub,Mul,Div}; //初始化函数指针数组
//调用
for(int i=0;i<4;i++){ //通过数组元素调用函数
pf[i](2,5);
}
这里pf先跟[4]结合,说明了pf是个数组,然后去掉pf[4],剩下的int(*)(int,int)就是数组里面存储的类型,这个类型就是函数指针。通过调用数组不同的元素就能调用到不同的函数。
既然是个数组,当然也可以定义一个指针,指向这个数组,一个指向函数数组的指针。
类型的写法就是取地址pf (&pf),原来的类型加上一个*,就是int ( *( *pf[4] ) )(int ,int)。注意不是int* ( *pf[4] )(int,int)
int *(pf[4])(int,int);
int (*(*ptr[4]))(int,int)=&pf;
PS:要注意函数数组的指针取地址得到的就不是本身了。
三.回调函数
1.定义
回调函数就是利用函数指针,来在函数内部调用不同的函数。
void test()
{
printf("hehe!\n");
}
void print_hehe(void (*pfun)()) //这个函数就叫回调函数
{
if(1)
pfun();
}
int main()
{
print_hehe(test);
}
print_hehe的形参是一个函数指针,只要给函数不同的函数指针的实参,就能调用不同的函数。
而这里print_hehe就是一个回调函数。
2.实例:
//简单的计算器实现
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 calc(int(*fun)(int,int))
{
int x,y;
scanf("%d%d",&x,&y);
int ret=fun(x,y);
printf("%d\n",ret);
}
int main()
{
int input=0;
scanf("%d",&input);
while(input){
switch(input){
case 1:
calc(Add);
break;
case 2:
calc(Sub);
break;
case 3:
calc(Mul);
break;
case 4:
calc(Div);
break;
}
}
return 0;
}
这种写法不仅能减少函数冗余,提高代码复用性,而且每次修改和添加代码增加删减功能的时候,修改的地方少,减少了函数代码的耦合度。
函数指针数组的写法:
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.加法 2.减法 ****\n");
printf("**** 3.乘法 4.除法 ****\n");
printf("**** 0.退出 ****\n");
}
int main()
{
int (*p[])(int, int) = { 0,Add,Sub,Mul,Div };
int input = 1, x = 0, y = 0;
menu();
printf("请选择:>\n");
while (input) {
scanf("%d", &input);
printf("请输入要计算的两个数:>\n");
scanf("%d %d", &x, &y);
int ret = p[input](x, y);
printf("%d\n", ret);
}
return 0;
}