回调函数
回调函数
回调函数的本质:函数指针的一种用法.
主要使用情形 :在分层的代码架构中,下层需要调用上层的函数.
例如:下层有串口驱动,只负责数据的收发. 当串口接收到不同的数据时,上层需要做出不同的处理. 这时处理函数(handler)可以在上层实现,下层通过回调的方式调用上层的处理函数.
1.函数指针
顾名思义,函数指针就是指向函数的指针。指针不只可以指向一个变量、数组,还可以指向一个函数。
我们已经知道,函数在编译后会有一个入口地址(或叫 函数地址),函数指针变量存的就是函数的入口地址。在定义指向变量或数组的指针时,需要确定指针的数据类型.那么在定义函数指针时,也需要确定函数的类型,包括函数的参数,返回值.
2.函数指针定义
举例: int (*func)(int,int); /* 第一个 int 是func所指向函数的返回值类型,后面的(int,int)意思是func所指向的函数接受两个 int 型的输入参数。*/
func 是函数指针变量名,*func 两边的()不能省略, 必须写成(*func)。因为()的优先级比 * 的高。 省略了的话,func就与后面的(int,int)结合了,那 func就是一个函数,而不是一个指针变量。从(*func)左右的内容可以看出,它指向一个这样的函数类型为: 有两个int型的形参,返回值也是 int 型。
3.使用函数指针
1、通过函数指针调用它所指向的函数。
例如:
int max(int a, int b); int min(int a, int b); int add(int a, int b); int (*func)(int,int); int a=1, b=2, c; func = max; c = (*func)(a, b); func = min; c = (*func)(a, b); func = add; c = (*func)(a, b);
这个例子中,我们省略掉了max,min,add函数的实现,从例子中可以看出,通过将func指针指向不同的函数,在调用该指针时,就等同于调用了它所指向的函数.
(拓展1:实际上,max,min,add 本身也是指针,指向那3个函数的入口地址. 只是习惯上我们通常写成 c = max(a,b)的格式,这样更加容易理解,而不会写成
c = (*max)(a, b)的格式。通过函数指针调用函数和直接通过函数名调用函数,不同的地方在于max, min, add 等函数名是固定地址的指针,他们只指向这3个函数的入口地址,而 func 是一个动态地址指针,它可以根据需要,指向不同的函数. 例子中求 c 的值时, 看上去都是调用同一个函数,而实际上这个指针在每次调用之前已经指向了不同的函数,于是得到了3个不同的值。
(拓展2:一个函数在编译链接之后就是一段代码数据,这段代码有一个起始地址, 在程序运行的过程中,调用某个函数实际就是跳转到这个函数的起始地址。这个函数的函数名就是保存这段代码起始地址的指针.例如上面的 max .就是一个指向那段代码的起始地址的指针,所以如果我们用 c = max(a,b) 时,会自动跳到mac函数的起始地址开始执行,并把执行完后的返回值赋给变量 c )
2、函数指针作为形参。
函数指针的另一个重要用途是把函数的地址作为参数传递到其他函数。
例如:
int func1(int a); int func2(int a, int b); void func3(int(*p1)(int), int(*p2)(int,int)); //定义func函数,形参是两个函数指针 { int i,j,m,n;
... i = (*p1)(m); j = (*p2)(m,n) } func3(func1, func2); //将func1,和func2作为参数传入func3
函数 func3() 的两个形参p1,p2是两个函数指针,而 func3() 的实参是 func1() 和 func2()。这么做的好处是,将来func3()可以使用别的函数作为实参,而不需要修改func3()本身。例如: func3(func4, func5)
这里 func1( ), func2( )就叫 回调函数(callback function).func( )是调用者,回调函数func1( ), func2( )是被调用者。

浙公网安备 33010602011771号