函数也有地址,指向函数的存储地址的数据类型为函数指针,在存储机器语言代码的内存块中,函数指针指向这个函数的内存块的开始地址。利用函数指针,我们可以使用一个函数找到另一个函数,亦或者让函数成为另一个函数的变量。那为什么不直接使用函数调用呢?因为函数调用的代码是写好的,只能调用那一个固定的函数,但是函数指针如果作为一个变量来使用的话,可以传入不同的值,即可以选择使用不同的函数。
获取函数指针
函数名(不带参数)即为指向该函数的指针,若将函数作为参数传递,必须传递函数名(函数指针):
invoke(myFunction); // 传入的是函数指针,即函数
invoke(myFunction()); // 传入的是函数的返回值
声明函数指针
声明函数指针时必须指定指针指向的函数类型,即说明函数的返回类型与参数列表,和函数原型的声明方式非常类似。
int myFunction(double); // 函数原型
int (*myFunctionPoint)(double); // myFunction是函数指针
这里将 (*myFunctionPoint)
替换了 myFunction
,从而 myFunction
是函数名, myFunctionPoint
是函数指针
注意区分如下的两种情况:
int (*myFunctionPoint)(double); // myFunction是函数指针
int * myFunction(double); // 返回一个指向int的指针的函数
在正确的声明函数指针后,要通过赋值使得函数指针指向函数,由于上文提到函数名(不带参数)即是函数的地址,从而赋值的方式就很简单(赋值必须保证返回类型和参数列表均相同):
myFunctionPoint = myFunction; // 左侧为函数指针,右侧为函数的地址
使用指针调用函数
已知,(*myFunctionPoint)
和myFunction
扮演的角色相同,所以可以使用任何一种形式来调用这个函数:
int result = myFunction(1.2); // 使用函数名调用函数
int result = (*myFunctionPoint)(5.6); // 使用函数指针调用函数
int result = myFunctionPoint(3.7); // 实际上这也是一种可行的方式
函数指针数组
函数指针的神奇之处在于它可以保存成数组类型。假设我们有三个返回类型和参数列表均相同但是作用却不同的函数:
double f1(int);
double f2(int);
double f3(int);
我们可以使用一个指向这种函数类型的函数指针的数组来存储这三个函数的指针:
double (*fp[3]) (int) = {f1,f2,f3};
现在说明一下数组索引3的位置:fp是一个包含三个元素的数组,而要声明这样的数组,首先需要使用fp[3]
,该声明的其他部分指出了数组包含的元素是什么样的。运算符[]
的优先级高于*
,因此fp[3]
表明fp
是一个包含三个指针的数组。上述声明的其他部分指出了每个指针指向的是什么:参数为int,且返回类型为double的函数。因此,fp
是一个包含三个指针的数组,其中每个指针都指向这样的函数,即将int作为参数,并返回一个double。
注意,此处无法使用auto赋值,因为auto只能用于单值初始化,无法用于初始化列表。
接下来使用该数组调用函数:
double = fp[0](1);
double = (*fp[1])(2);
转载请注明出处,本文永久更新链接:https://blogs.littlegenius.xin/2019/08/12/【C-温故知新】四函数/函数指针