Chinaunix首页 | 论坛 | 博客
  • 博客访问: 802419
  • 博文数量: 330
  • 博客积分: 9641
  • 博客等级: 中将
  • 技术积分: 3181
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
文章分类

全部博文(330)

文章存档

2012年(17)

2011年(135)

2010年(85)

2009年(57)

2008年(36)

我的朋友

分类: C/C++

2011-02-28 16:17:00

【函数指针】

       在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。

1.函数指针定义

函数类型 (*指针变量名)(形参列表);

“函数类型”说明函数的返回类型,由于“()”的优先级高于“*”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。

例如:

int (*f)(int x);

double (*ptr)(double x);

在定义函数指针时请注意:
    
函数指针和它指向的函数的参数个数和类型都应该是—致的;

函数指针的类型和函数的返回值类型也必须是一致的。

2.函数指针的赋值

函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。

例如,

int func(int x);   /* 声明一个函数 */

int (*f) (int x);    /* 声明一个函数指针 */

f=func;            /* 将func函数的首地址赋给指针f */

赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。

3.通过函数指针调用函数

函数指针是通过函数名及有关参数进行调用的。

与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则*pi等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则*pf就等价于它所指的变量f。同样地,f是指向函数func(x)的指针,则*f就代表它所指向的函数func。所以在执行了f=func;之后,(*f)和func代表同一函数。

由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步:

首先,要说明函数指针变量。

例如:int (*f)(int x);

其次,要对函数指针变量赋值。

例如: f=func;    (func(x)必须先要有定义)

最后,要用 (*指针变量)(参数表);调用函数。

例如:    (*f)(x);(x必须先赋值)

函数指针是一个指向函数的指针,而指针函数只是说明他是一个返回值为指针的函数。


传递回调函数的地址给调用者
    现在可以将p传递给另一个函数(调用者)- caller(),它将调用p指向的函数,而此函数名是未知的:
void (*p) (); //p是指向某函数的指针
void caller(void(*ptr)())
{
ptr(); /* 调用ptr指向的函数 */  //回调函数不用这样(*ptr)()
}
void func();
int main()
{
p = func; 
caller(p); /* 传递函数地址到调用者 */
}

    如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。

man 3 ldopen 里面的例子:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dlfcn.h>
  4. int main(int argc, char **argv) {
  5.     void *handle;
  6.     double (*cosine)(double);
  7.     char *error;
  8.     handle = dlopen ("libm.so", RTLD_LAZY);
  9.     if (!handle) {
  10.         fprintf (stderr, "%s\n", dlerror());
  11.         exit(1);
  12.     }
  13.     dlerror(); /* Clear any existing error */
  14.     cosine = dlsym(handle, "cos");
  15.     if ((error = dlerror()) != NULL) {
  16.         fprintf (stderr, "%s\n", error);
  17.         exit(1);
  18.     }
  19.     printf ("%f\n", (*cosine)(2.0));
  20.     dlclose(handle);
  21.     return 0;
  22. }

参考链接:
阅读(526) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~