#include
int sum(int x,int y)
{
return x+y;
}
int main()
{
int(*p)(int,int)=∑
printf("%d\n",p(2,3));
return 0;
}
我们没有通过sum直接调用函数,而是通过一个指针调用了函数sum。我们把 这种指向函数的指针叫做函数指针。
函数指针:指向函数的指针!
(存放函数的地址)
函数指针是指向函数的地址,那函数真的有地址吗?
我们打印来看看:
printf("%p\n",&sum);
我们在学习数组时知道 &arr 与 arr都是数组首元素的地址。那函数的地址是否类似呢?
我们再来看看:
printf("%p\n",&sum);
printf("%p\n",sum);
果然如此,&sum与sum都指向了同一个地址。
结论:取地址函数名和函数名都是函数的地址。
那么,我们该如何写一个函数指针呢?
是这样吗?
int* p(int int)=sum;
我们发现,这样是不行的。
这样写的话p会首先与括号先结合,让p变成了个函数名,int* 变成了返回类型。这样是不对的。
所以我们需要写个括号把*与p结合变成个指针:
int (*P)(int,int)=sum;
这段代码的意思是,我定义了个指针 *p 它指向了函数 sum,函数形参是 (int,int),函数的返回值是最前面的int;
也可以写成:
int (*P)(int x,int y)=sum;
printf("%d\n",(*p)(2,3));
我们就只需要 对指针p进行解引用 (*p),就是所要函数,再输入实参 (2,3),即可计算出结果。
我们再来看下一段代码:
printf("%d\n", (p)(2, 3));
printf("%d\n", (*p)(2, 3));
printf("%d\n", (**p)(2, 3));
printf("%d\n", (***p)(2, 3));
我们发现不管有没有,有几个 * 都对调用没有影响。
为什么没有 * 也可以调用函数呢?
printf("%d\n", p(2, 3));
printf("%d\n", sum(2, 3));
我们发现,其实p与sum都指函数的地址,所以说,没有对p进行解引用都可以调用函数。
注意:
printf("%d\n",*p(2, 3));
不可以这样写!!
p(2,3)先结合,已经返回了int类型的值,不可再解引用!!
前面我们学习了数组,数组是存储同一种数据类型多个元素的集合。那我们可不可以写一个数组,数组的每个元素都是一个函数指针呢?
#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 main()
{
int(*parr[3])(int x, int y) = { add,sub,mul };
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d\n", parr[i](2, 3));
}
return 0;
}
int(*parr[3])(int x, int y) = { add,sub,mul };
我们来分析一下这个定义。
parr首先与[3]结合变成一个数组,数组名parr,元素个数3;
剩下的 int(*)(int x, int y) 就是一个函数指针类型。
我们就这样,定义了一个函数指针数组。
我们就能够通过访问数组元素来调用数组里的每个函数了。
学过这些内容后,我们不妨可以试试,使用函数指针数组,写一个可以进行加减乘除的计算器。代码如下:
#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("**************************\n");
printf("**** 1. add 2. sub ****\n");
printf("**** 3. mul 4. div ****\n");
printf("**** 0. exit ****\n");
printf("**************************\n");
}
int main()
{
int input = 0;
do {
menu();
int x = 0;
int y = 0;
int ret = 0;
int(*p[5])(int, int) = { 0,Add,Sub,Mul,Div };
printf("请选择:>");
scanf("%d", &input);
if (input == 0)
{
printf("退出程序\n");
break;
}
else if (input >= 0 && input <= 4)
{
printf("请输入2个操作数>:");
scanf("%d %d", &x, &y);
ret = p[input](x, y);
printf("sum = %d\n", ret);
}
else
{
printf("选择错误,请重新选择\n");
}
} while (1);
return 0;
}
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
#include
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int clac(int (*p)(int, int),int x,int y)
{
return p(x, y);
}
int main()
{
int x = 2, y = 3;
printf("%d\n", clac(Add, x, y));
printf("%d\n", clac(Sub, x, y));
return 0;
}
我们发现,我们通过给clac函数传递了Add或Sub的地址,与整型变量x,y来实现了回调函数的应用。
int x = 2, y = 3;
int (*pa)(int, int) = Add;
int (*pb)(int, int) = Sub;
printf("%d\n", clac(pa, x, y));
printf("%d\n", clac(pb, x, y));
我们也可以这样写来传递Add与Sub函数的地址。
函数指针的内容就介绍到这里吧,感谢各位读者的阅读,如果觉得笔者写得还可以的话,麻烦各位友友们一键三连哦!非常感谢!如果笔者这篇文章有什么错误和不足的地方,也恳请大家不吝赐教!