函数指针的定义:如果在程序中定义了一个函数,在编译时,编译系统会为函数代码分配一段存储空间,而这段存储空间的起始地址(入口地址)称为这个函数的指针。
使用时,函数名就是地址,跟数组名的地址有异曲同工之妙。
那么如何定义一个函数指针。其实与普通变量一样,例如 int a, int *p; char a, char *p依次类推,函数声明:int getData(int a ,int b); 则函数指针声明int (p) (int a,int b); 其中值得注意的 是,(p)需要用括号括起来,由于优先级的原因。如果没有写括号,则实际上就写了个指针函数返回值为int *型
我们如何来使用呢,接下来我们来试一试:
实际上,函数调用概念和变量一样。
例如之前使用变量时,我们可以直接使用变量名来进行直接操作,例如int a = 1;也可以使用地址来进行间接操作。例如int *p = &a; *p = 1;等。函数调用也是如此,可以使用函数名直接调用,或者使用函数指针来间接调用。
#include "stdio.h"
void PrintWelcome()
{
printf("Hello, welcome\n");
}
int main()
{
// 直接函数名调用:
PrintWelcome();
// 定义一个函数指针来调用.
void (*p)() = PrintWelcome;
(*p) ();
return 0;
}
运行结果如下:
vxbus@vxworks:~/github/code$ ./test
Hello, welcome
Hello, welcome
vxbus@vxworks:~/github/code$
发现其效果是一样的。但是值得注意的是,你要定义一个函数指针来指向一个函数,那么你函数指针的数据类型,应该要与你想所指的函数的类型一致。
函数指针的好用之处
为了更好地使用函数指针,我们来做一个练习:现在有个题目:
有两个整数a和b,由用户输入1,2或3.如输入1则给出ab中大的数,如果输入2则给出小的,如果输入3则输出两数之和。
我们通过用户输入的数值不同,通过switch将不同情况将函数指针指向不同的函数。最后通过dataHandler()函数统一调用函数。
#include "stdio.h"
#include "stdlib.h"
/*
用户输入一个数字
通过1取最大值,2取最小值,3求和
*/
int GetMax(int data1,int data2)
{
return data1>data2?data1:data2;
}
int GetMin(int data1, int data2)
{
return data1 < data2 ? data1 : data2;
}
int GetSum(int data1,int data2)
{
return data1+data2;
}
int dataHandler(int data1, int data2, int (*pfunk)(int data1, int data2))
{
int data;
data = (*pfunk)(data1, data2);
}
int main()
{
int a = 10;
int b = 20;
int cmd;
int ret;
int (*pfunk)(int data1, int data2);
printf("请输入一个数字1、取最大值 2、取最小值 3、取两数之和");
scanf("%d", &cmd);
switch(cmd){
case 1:
printf("最大值为:");
pfunk = GetMax;
break;
case 2:
printf("最小值为:");
pfunk = GetMin;
break;
case 3:
printf("和为:");
pfunk = GetSum;
break;
default:
printf("输入错误");
exit(-1);
}
ret = dataHandler(a, b, pfunk);
printf("ret =%d \n", ret);
return 0;
}
运行结果如下:
vxbus@vxworks:~/github/code$ ./test
请输入一个数字1、取最大值 2、取最小值 3、取两数之和1
最大值为:ret =20
vxbus@vxworks:~/github/code$ ./test
请输入一个数字1、取最大值 2、取最小值 3、取两数之和2
最小值为:ret =10
vxbus@vxworks:~/github/code$ ./test
请输入一个数字1、取最大值 2、取最小值 3、取两数之和3
和为:ret =30
vxbus@vxworks:~/github/code$
通过这个案例,你能否了解到,其中的妙处。
总结
函数指针在声明时由于优先级原因,记得要加括号,不然会变成一个指针函数。
函数指针指向函数时,函数指针外形应该跟函数长得一样,其中函数指针中的形参的名字可以直接省略,例如int (*pfunk)(int data1, int data2)其中的data1和data2 可以不写直接int (*pfunk)(int, int )也是不会有错误的。