函数指针与函数回调
1、函数指针
C/C++中可以使用指针指向一段代码,这个指针就叫函数指针,假设有这样一段代码:
1 2 3 4 5 6 7 8 | #include <stdio.h> int func( int a) { return a + 1 ; } void main() { int (*f)( int ) = func; printf( "%p\n" , f); } |
定义了一个函数func,然后使用指针变量f指向该函数,然后打印出变量f指向的地址:
1 2 | ./a.out 0x400526 |
函数指针本质也是一个指针,只不过这个指针指向的不是内存中的一段数据而是内存中的一段代码,在这个示例中指向了内存地址0x400526,在这个地址中保存了函数func的机器指令。函数调用,就是 CPU 跳转到某个函数的首地址,继续执行。但仅仅知道函数的首地址,是不够的!因为在调用之前,主调函数还需要为被调函数准备参数。
2、回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
为什么要使用回调函数?
在调用库函数时,我们往往不会去修改库函数的内容,而我们却又想通过一个函数实现多个函数的功能,使用回调函数,将会大大的减少我们的。如,我们在做一个特大项目时,某个函数需要调用其它不同的函数实现不同的功能,假设可供调用的函数有100个,那我们是不是要写封装100个这样的函数?这样可以是可以,但很累人,一分钟不加班就不自在的朋友可以考虑下。但引用回调函数机制会大大减少我们工作量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #include<stdio.h> int CallbackFunction1() { printf( "This is CallBack Function1\n" ); return 0 ; } int CallbackFunction2() { printf( "This is CallBack Function2\n" ); return 0 ; } int Handle( int (*p)()) { (*p)(); return 0 ; } int main() { Handle(CallbackFunction1); Handle(CallbackFunction2); } #include <stdio.h> int op( int a, int b, int (*p)( int , int )); int __add( int a, int b); int __sub( int a, int b); int __mul( int a, int b); int main() { int a = 2 ,b = 3 ,re; re = op(a,b,__add); printf( "%d\n" ,re); return 0 ; } int op( int a, int b, int (*p)( int , int )) { return p(a,b); } int __add( int a, int b) { return a+b; } int __sub( int a, int b) { return a - b; } int __mul( int a, int b) { return a*b; } |
3、回调
回调(call back)是一个过程,回调函数(call back funciton)是这个过程中的一个函数;
再明确一点,回调函数和普通函数没有任何差别,是的,没有任何差别,你想怎么写就怎么写,只要能满足需求。
回调的本质:把指向回调函数的指针作为参数传给其他函数,其他函数通过这个指针就能使用回调函数。
回调过程涉及3个部分,调用者、使用回调函数的函数、回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include<stdio.h> //回调函数1 int cbfunc1( int a, int b) { return a - b; } //回调函数2 int cbfunc2( int a, int b) { return a*2 - b; } //使用回调函数的函数 int func( int (*cb)( int , int )) { int op1 = 10; int op2 = 25; int ret = cb(10, 25); return ret; } //调用者 int main() { int ret1, ret2; ret1 = func(cbfunc1); ret2 = func(cbfunc2); printf ( "ret1 = %d\n" , ret1); printf ( "ret2 = %d\n" , ret2); return 0; } 输出结果: ret1 = -15 ret2 = -5 |
int func(int (*cb)(int, int)) 的参数是一个函数指针
回调过程:main函数调用func函数,把cbfunc作为指针参数传给func, func运行时会通过这个指针去调用指向的函数。
说白了就是,main调用func,func调用cbfunc(单线程的情况下),特殊的地方就是func通过指针调用cbfunc。
用途:
调用不在同一区域的函数,比如动态库想调用外边的函数,就可以写一个回调;用void指针可以让回调更灵活。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2020-04-30 Java NIO
2020-04-30 并发之Atomic类与Unsafe类
2020-04-30 Java并发容器总结
2020-04-30 ReentrantLock源码分析