函数指针和指针函数
函数指针:
int func ( );
int (*func) ( ); //指针两侧的括号不能省略,表示先对func解引用,然后再调用相应的函数
函数指针是一个指向函数的指针, 其实就是函数, 因为ANSI C标准将func ( )认为是(*func)( ) 的简写形式 ,并且推荐使用func ( )形式,因为它更符合函数调用的逻辑。
注:
但是我在测试的时候,定义为int func ( );和定义为int (*func) ( );还是有差别的,
int func ( );表示定义了一个函数
int (*func) ( );表示定义了一个指向函数的指针。
函数指针的使用:
void test ( );
int wrong_match (int);
void (*ptf) ( );
下面的初始化是错误的,因为函数指针的类型与函数的类型不 匹配:
test = wrong_match;
test = & wrong_match;
ptf = wrong_match;
ptf = & wrong_match;
以下初始化及赋值是合法的:
ptf = test;
ptf = &test;
C语言规定函数名会被转换为指向这个函数的指针,除非这个函数名作为 & 操作符或sizeof操作符的操作数。
( 注意:函数名用于 sizeof 的操作数是非法的 )
也就是说,在
ptf = test;
中test被自动转换为&test。
而在
ptf = &test;
中已经显示使用了&test,所以test就不会再发生转换了。
因此直接引用函数名等效于在函数名上应用 & 运算符,两种方法都会得到指向该函数的指针。
测试例程和运行结果:
pointer_to_func.c文件:
1 #include <stdio.h>
2
3 int testfunc(void)
4 {
5 printf("%s: call me(%p)./n", __func__, testfunc);
6 return 0;
7 }
8
9 int main(int argc, char *argv[])
10 {
11 /* define a pointer to function */
12 void (*func)(void);
13 //void func(void);
14
15 func = (void *)testfunc;
16
17 printf(" testfunc(%p)/n", testfunc);
18 printf("&testfunc(%p)/n", &testfunc);
19 printf("*testfunc(0x%x)/n", *testfunc);
20
21 /* run function */
22 func();
23 (*func)();
24
25 return 0;
26 }
输出结果:
[lhcX86@horizon tmp]$ make pointer_to_func
cc pointer_to_func.c -o pointer_to_func
[lhcX86@horizon tmp]$ ./pointer_to_func
testfunc(0x8048374)
&testfunc(0x8048374)
*testfunc(0x8048374)
testfunc: call me(0x8048374).
testfunc: call me(0x8048374).
指针函数:
指针类型的函数,返回指针的函数。注意函数的返回值不仅仅局限于指向变量的指针,也可以是指向函数的指针。
首先来看这个声明:
int (* function(int) ) (double*, char);
要了解此声明的含义,首先来看function(int),将function声明为一个函数,它带有一个int型的形式参数,这个函数的返回值为一个指针,正是我们本将开头讲过的函数指针 ── int (*) (double*, char);
这个指针指向一个函数,此函数返回int型并带有两个分别是double*型和char型的形参。如果使用typedef可以将这个声明简化:
定义一个 ptf 为这个 函数指针的类型:
typedef int (*ptf) (double*, char);
定义返回值类型为ptf 函数指针的指针函数:
ptf function( int );
要说明一下,对于typedef int (*ptf) (double*, char);
注意:
不要用#define的思维来看待typedef,如果用#define的思维来看的话会以为(*ptf)(double*, char)是int的别名,但这样的别名看起来好像又不是合法的名字,于是会处于迷茫状态。
实际上,上面的语句把ptf定义为一种函数指针类型的别名,使得ptf和函数指针类型int (*) (double*, char);等价 。
回调函数
为什么要使用回调函数?
回调函数是一个程序员不能显式调用的函数;
通过将回调函数的地址传给 调用者从而实现调用。
在我们想通过一个统一函数接口实现不同的内容 ,这时用回掉函数非常合适。
什么是回调函数?
简而言之,回调函数是一个通过函数指针调用的函数。如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。
例子:
下面时一个简单的回调函数的例子,供理解:
callback.c
1 /*
2 * callback.c
3 *
4 * 4bsfreedom(at)gmail.com
5 * */
6
7 #include <stdio.h>
8
9 int func1(void)
10 {
11 printf("I'm callback function/n");
12
13 return 0;
14 }
15
16 int func2(int x)
17 {
18 printf("func2 x is (%d)/n", x);
19
20 return 0;
21 }
22
23 int func3(int x)
24 {
25 x = 2345;
26 printf("do different thing in func3 (%d)/n", x);
27
28 return 0;
29 }
30
31 void callback_test( int(*func)() )
32 {
33
34 /* callback function here */
35 (*func)();
36 }
37
38 void callback_api( int(*func)(), int bb)
39 {
40
41 /* callback function here */
42 (*func)(bb);
43 }
44
45 int main(int argc, char * argv[])
46 {
47 //printf("%d/n", argc);
48 callback_test(func1);
49 callback_api(func2, argc);
50 callback_api(func3, argc);
51
52 return 0;
53 }
运行结果:
[lhcX86@horizon tmp]$ make callback
cc callback.c -o callback
[lhcX86@horizon tmp]$ ./callback
I'm callback function
func2 x is (1)
do different thing in func3 (2345)
References:
《探讨C语言中的回调函数》
http://www.blogjava.net/huyi2006/articles/180169.html
《异步消息的传递-回调机制》
http://www.ibm.com/developerworks/cn/linux/l-callback/index.html
《分清函数指针和指针函数》
http://blog.csdn.net/porscheyin/archive/2008/12/06/3461632.aspx
PS:
为了加深自己的理解,和一些其它的C语言基本功,我最近查看了三本经典书籍来补充C语言知识,书名这里与大家共享一下。
《C Traps and Pitfalls》(C陷阱与缺陷) Andrew Koenig 著
《The C Programming Language》(C程序设计) Dennis M.Ritchie 著
《高质量程序设计指南──C/C++》林锐 韩永泉 著