当前位置:文档之家› C语言学习笔记之函数指针

C语言学习笔记之函数指针

C/C++学习笔记之函数指针
函数指针的概念,在潭浩强先生的《C语言程序设计》这本经典的教程中提及过,在大多数情况下我们使用不到,也忽略了它的存在。

函数名实际上也是一种指针,指向函数的入口地址,但它又不同于普通的如int*、double*指针,看下面的例子来理解函数指针的概念:view plain int function(int x,int y);
int main(void)
{
int(*fun)(int x,int y);
int a=10,b=20;
function(a,b);
fun=function;
(*fun)(a,b);……
}
第一行代码首先定义了一个函数function,其输入为两个整型数,返回也为一个整型数(输入参数和返回值可为其它任何数据类型);后面又定义了一个函数指针fun,与int*或double*定义指针不同的是,函数指针的定义必须同时指出输入参数,表明这是一个函数指针,并且*fun也必须用一对括号括起来;并将函数指针赋值为函数function,前提条件是*fun 和function的输入参数和返回值必须保持一致,否则无法通过编译。

可以直接调用函数function(),也可以直接调用函数指针,二者是等效的。

回调函数(callback)是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。

简而言之,回调函数就是一个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。

要实现回调,必须首先定义函数指针。

尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。

请看下面的例子:
void f();//函数原型
上面的语句声明了一个函数,没有输入参数并返回void.那么函数指针的声明方法如下:void(*)();
函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?
如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。

定义一个指向函数的指针用如下的形式,以上面的test()为例:
int(*fp)(int a);//这里就定义了一个指向函数的指针
函数指针绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。

int*fp(int a);//这里是错误的,因为按照结合性和优先级来看就是先和()结合,然后变成了一个返回整型指针的函数了,而不是函数指针,这一点尤其需要注意!
例如函数原型为:
int fun(int*,int);
则函数指针可以声明为:int(*pf)(int*,int);当然从上述例子看不出函数指针的优点,目的主要是想引出函数指针数组的概念。

我们从上面例子可以得知,既然函数名可以通过函数指针加以保存,那们也一定能定义一个数组保存若干个函数名,这就是函数指针数组。

正确使用函数指针数组的前提条件是,这若干个需要通过函数指针数组保存的函
数必须有相同的输入、输出值。

//定义256个处理函数(及其实现)。

int function0(int*,int);
……
int function255(int*,int);
//其次定义函数指针数组,并给数组赋值。

void(*fun[256])(int*,int);
fun[0]=function0;
……
fun[255]=function255;
如果赋了不同的值给函数指针,那么调用者将调用不同地址的函数。

赋值可以发生在运行时,这样使你能实现动态绑定。

下面我们来看一个具体的例子:
int test(int a)
{return a;}
int main(void)
{
int(*fp)(int a);
fp=test;//将函数test的地址赋给函数指针fp
cout<<fp(5)<<"|"<<(*fp)(10)<<endl;
/*输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!*/
return0;}
typedef定义可以简化函数指针的定义,在定义一个的时候感觉不出来,但定义多了就知道方便了,上面的代码改写成如下的形式:
int test(int a)
{return a;}
int main(void)
{typedef int(*fp)(int a);
/*注意,这里不是声明函数指针,而是定义一个函数指针的类型,这个类型是自己定义的,类型名为fp*/
fp fpi;//这里利用自己定义的类型名fp定义了一个fpi的函数指针!
fpi=test;
cout<<fpi(5)<<"|"<<(*fpi)(10)<<endl;
/*输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!*/
return0;}。

相关主题