目录
函数其实也是有地址的,函数名就是函数的地址,&函数名也是函数的地址。所以就存在函数指针,而有了函数指针就有函数指针数组,那有了函数指针数组,不就又有了指向函数指针数组的指针了嘛,这不就成了套娃吗。
函数指针的类型与使用
首先知道它是一个指针所以就(*p)表示指针,其它就是照搬函数类型了。而使用方法就可类似函数的形式。
#include<stdio.h>
int Max(int x, int y)
{
return (x > y ? x : y);
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int(*p)(int ,int) = Max;//函数名就是地址,p指向Max地址
//函数类型是int (int ,int)
//函数指针变量p的类型就是int (*)(int ,int)
//使用:
int ret = (*p)(a, b);//这里(*p)就相当于Max函数
printf("%d", ret);
return 0;
}
其实在你编译的时候 int ret=(*p)(a,b) 中的 * 也是可以省略的,不影响结果,p实际指向的就是Max函数。 (主要还是由于函数名与&函数名都表示函数的地址,所以就有这种效果,即:不管你前面有多少*操作都不影响执行,所以 * 就如同摆设)
解读函数指针
代码一
(*( void(*)() )0)()
先分析,从里向外看,void(*)() 这不就是函数指针类型嘛,是无参且无返回值的函数指针类型,然后就被括起来加了个0,0是一个int类型的数,前面部分不就相当于强制类型转换嘛,将int(0)强制类型转换成函数指针类型,相当于0地址处放一个无参无返回值的函数,外面解引用加个空括号,那不就是调用0地址处的函数嘛。
代码二
void(* signal(int,void(*)(int)))(int)
同代码一的分析,先看里面的 signal(int,void(*)(int)) 不就是一个signal 的函数嘛,一个参数是int 类型,另一个参数是void(*)(int)函数指针类型,此时是不是就想到函数还差的一个部分(返回类型)呢,确实外面部分的void(*)(int)就是函数signal的返回类型,而返回类型也是一个函数指针,那为什么会分开写呢?返回类型 void(*)(int)不应该写在前面嘛。所以这就是函数的声明。
当我们使用 typdef 进行类型的重命名时,名字必须写在*的后面。
1.typedef void(*)(int) typ_t//这种就无法执行下去
2.typedef void(*typ_t)(int) //将void(*)(int)重命名为typ_t这个类型名
函数指针数组
见名知意,函数指针数组就是存放函数指针的数组。假如我们现在有几个相同返回值和参数的函数,那么我们就可以用函数指针数组存放起来。
#include<stdio.h>
int sum(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 main()
{
int (*p[4])(int, int) = { sum,sub,mul,div };//创建函数指针数组,p[4]就是表示数组,
//其余分就是函数指针数组的类型,因为这四个函数的类型(参数与返回值)是一样的才可以放在一起。
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("******************************\n");
printf("**** 1. add 2.sub *****\n");
printf("**** 3. mul 4.div *****\n");
printf("**** 0. exit *****\n");
printf("******************************\n");
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
//转移表 - 函数指针的数组
int (*pfArr[])(int, int) = {NULL, Add, Sub, Mul, Div};//创建函数指针数组放置这几个函数的地址,数组首元素放个NULL为了占据一个位置,方便后续的循环执行。
//0 1 2 3 4
do//该循环de效果最为好
{
menu();
printf("请选择:>");
scanf("%d", &input);
if (input == 0)
{
printf("退出计算器\n");
break;
}
else if (input >= 1 && input <= 4)
{
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
int ret = pfArr[input](x, y);//调用函数指针数组,pfArr[input]就表示指向的是第什么函数
printf("%d\n", ret);
}
else
{
printf("选择错误\n");
}
} while (input);//为假退出循环
return 0;
}
编译就留给你们了!
指向函数指针数组的指针
函数指针数组当然也可以放在一个指针当中了,而这个指针的类型同样与函数指针有关。
假如就拿上面的函数指针数组举例 int (*ptArr[4])(int ,int) 是一个函数指针数组,把它放在一个指针里,(*p)表示指针,其他部分就照搬函数指针数组的类型就行,即: int (*(*pt)[4])(int ,int)
指向的就是函数指针数组的指针变量 p