浅谈函数指针

来源:互联网 发布:mysql客户端工具 编辑:程序博客网 时间:2024/05/01 19:13

 函数指针的概念,在潭浩强先生的C语言程序设计这本经典的教程中提及过,在大多数情况下我们使用不到,也忽略了它的存在。函数名实际上也是一种指针,指向函数的入口地址,但它又不同于普通的如int*、double*指针,看下面的例子来理解函数指针的概念:

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(),也可以直接调用函数指针,二者是等效的。

声明函数指针

    回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子:

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语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!return 0;} 

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语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!return 0;} 


 



 

原创粉丝点击