免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 707 | 回复: 0
打印 上一主题 下一主题

函数指针(转) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-01 21:02 |只看该作者 |倒序浏览

原文:http://www.i170.com/Article/63999/trackback
推荐和参考的材料:
http://www.newty.de/fpt/intro.html
更加高级的语言里面,几乎看见不到指针的影子,因为大多数人看来它是危险的,不小心可能导致内存泄漏等问题的发生,不过我们不用担心函数指针会发生类似的问题,因为分配内存和清理内存的操作重来不会发生。
函数指针指向一个函数的地址(不仅仅只有变量才有地址,程序代码会被分配一定的内存空间)

函数指针主要可以实现后期绑定(late-binding),这是有一定的实用价值的,不过这里注意一下,late-banding一般是OOP中的概念。

下面是一个简单的例子,给大家一个初步的印象:
#include
float add(float a, float b){
return a + b;
}
float mult(float a, float b){
return a * b;
}
float sub(float a, float b){
return a - b;
}
float div(float a, float b){
return a / b;
}
float getAns(float a, float b, float
(*prtF)(float, float)){
return (*prtF)(a,b);
}
int main(){
printf("%g\n",getAns(1,2,&add));
printf("%g\n",getAns(1,2,&sub));
return 0;
}

1. 定义一个函数指针:
int (*PRF)(int, char, float) = NULL;
这样定义了一个函数指针变量
PRF,它保存着指向这样的函数的指针:返回类型为 int,参数列表为(int,
char, float);
这里注意一下,PRF 被看做一个变量
前面有谈到 typedef
可以定义一个类型名,那么我们可以定义这样的一个类型名:
typedef int (*PRF)(int, char, float);
这时候,PRF 成为一个类型名,而不是一个变量。
关于typedef,可以参考:
http://www.i170.com/user/killercat/Article_64000

2. 取函数的地址:
和取变量地址一样,使用
&函数名,请看上面的例子,取add函数的地址为:&add

3. 关于调用约定:
看到这里,我们知道,对于一个函数指针变量,我们可以给它一个函数的地址,注意一下,函数指针在定义的时候使用如下格式:
返回类型 (*变量名)(参数列表);
这个函数指针变量,只能保存有着相同的返回类型和参数列表的函数指针。其实除了这两点之外,还需要注意一下调用约定。在Windows程序设计中,我们常见到的一个函数指针定义成:
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UNIT, WPARAM,
LPARAM);
初学者一眼就看蒙了,其实这里就是定义了一个类型名(或称之为类型,这两个概念在某些书上是不区分的):WNDPROC,它可以用来定义函数指针。这里有点不一样的是
CALLBACK,在Windows中,CALLBACK被这样定义:
#define CALLBACK   
__stdcall
__stdcall是调用约定(有关调用约定的内容可以在
http://www.i170.com/user/killercat/Article_63188
的后半部分找到),注意一下:
typedef LRESULT (__stdcall* WNDPROC)(HWND, UNIT, WPARAM,
LPARAM);
typedef LRESULT (__cdecl* WNDPROC)(HWND, UNIT, WPARAM,
LPARAM);
那么这里的2个 WNDPROC
就表达了不同的意思了,也就是说,某个函数指针变量保存的函数指针,不但要求有着相同的返回类型和参数列表,还需要相同的调用约定。
在默认情况下(不写调用约定)采用 __cdecl 的调用约定。

4. 函数指针变量是可以比较的(同于一般的指针变量)

5. 函数指针变量的另一种使用方式:
除了前面说的赋值,比较之外,函数指针还可以这样用:
#include
float add(float a, float b){
return a + b;
}
int main(){
float (*t)(float, float) = &add;
printf("%g\n",(*t)(1,2));
return 0;
}
注意到 (*t)(1,2); 等价于 add(1,2);
也就是一个函数指针变量可以看作是一个函数名,这里注意一下,使用的是
(*t) 来表示函数名,在C++中,使用的是 t,也就是 t(1,2)
对于C语言里面使用(*t),可以理解成为,取出指针t指向的具体的值,即函数。
这种用法,通常使用在把函数指针作为参数传递的时候:
void PassPtr(int (*pt2Func)(float, char,
char))
{
   int result = (*pt2Func)(12, 'a', 'b');
}

6. 函数指针可以被函数返回(同于普通变量)

7. 用数组来保存函数指针:
int (*fp[[color="#ff0080"]10])(float, char, char) =
{NULL};
或者
typedef int (*FP)(float, char, char);
FP fp[10] = {NULL};

http://www.i170.com/Article/63999/trackback
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/11176/showart_312363.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP