标题: 关于C语言回调函数的理解 [打印本页]
作者: IdeaMing 时间: 2019-1-3 14:03
标题: 关于C语言回调函数的理解
回调函数的理解
前言: 刚开始用C语言听说过回调函数,但没有仔细去理解,随着工作的慢慢积累,逐步的用到了回调函数,本人认为,“回调函数”的理解对于很多人是一个槛,要想跨过,就得理解清楚,还得会用。这里就用本人的方式讲解一下回调函数如何理解。如有问题,欢迎指正mr.li.ming@qq.com。
第一步:通俗的解释“回调函数”一、回调就是一种利用函数指针进行函数调用的过程。
二、你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。
三、回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。
注:以上解释均摘自网络,感谢这些大佬的解释。
或许到这里你已经明白了那么个意思,但是问题来了:
1. 怎么看出来就是一个回调函数呢?
2. 怎么定义一个回调函数呢?
3. 怎么使用回调函数呢?
带着问题我们看实例,然后再解释。
第二步:实例解释
- #include "stdio.h"
- int sub(int a, int b)//求和函数
- {
- return a+b;
- }
- int mul(int a, int b)//求积函数
- {
- return a*b;
- }
- int test(int(*p)(int,int), int a, int b)//测试函数
- {
- return (*p)(a, b);
- }
- void main(void)
- {
- int a = 8;
- int b = 2;
- int temp;
- temp = test(sub, a, b);
- printf("%d\n",temp);
- temp = test(sub, a, b);
- printf("%d\n",temp);
- }
- 执行结果就是
- 10 //8+2
- 16 //8*2
复制代码主要分析这个test函数,它的三个输入参数分别是
int(*p)(int, int) int a int b
后面两个好理解,就是跟常见的一样,是一个函数的两个输入参数。
第一个要怎么理解呢?
首先看到有*p,这是一个指针了,类比到int *a这种定义方式来理解。
Int temp; //定义一个int型的变量,名称是temp
Int *a;//定义一个 名称为a的指针这个指针限定的范围是“int型变量”
那么int(*p)(int, int)它的意思是:定义一个名称为p的函数指针, p指向的函数要求有两个int输入参数,而且要求这个函数返回值是int型。
那么趁热打铁void(*p)(int, int)的意思就是:定义一个名称为p的函数指针, p指向的函数要求有两个int输入参数,而且要求这个函数返回值是void型(即没有)。
void(*p)(int)的意思就是:定义一个名称为p的函数指针, p指向的函数要求有一个int输入参数,而且要求这个函数返回值是void型(即没有)。
char(*p)(int)的意思就是:定义一个名称为p的函数指针, p指向的函数要求有一个int输入参数,而且要求这个函数返回值是char型。
那么现在有没有明白这个参数的定义呢?
有篇资料中有这么一段
『函数指针的定义比较怪,为什么不是 void ()(int, int, float) *p_func
而是 void(*p_func)(int, int, float) 这种形式?』
这个问题我也不知道,也没必要纠结,花点时间理解下它与普通指针的区别,记住这就是它的定义形式。
到这里:总结一下,上面的这么多都是在解释一个“函数指针”。理解了函数指针,我们再看一下
int test(int(*p)(int,int), int a, int b)//测试函数
{
return (*p)(a, b);
}
这个test函数是把 p 这个函数指针作为一个输入参数。
temp = test(sub, a, b);
这一句呢,就是把p指向sub这个函数, Sub要求有两个int输入参数。
Return (*p)(a,b);就是
Return sub(a,b);这里 *p这个参数起作用了,这个参数就是sub函数,就是一个算法。
第三步:疑问解惑现在来回答第一步的三个问题了:
1、 怎么看出来就是一个回调函数呢?
像test函数那样,用了函数指针作为输入参数的函数就是回调函数,这种函数会调用另外一个函数作为输入参数。
2、 怎么定义一个回调函数呢?
回调函数定义跟上面的识别是反过来的,定义一个函数,它的输入参数中有函数指针,那么你就定义了一个回调函数。
3、 怎么使用回调函数呢?
使用回调函数的地方有很多,一般用于封装的程序给开发人员留出后期开发接口。
- int test(int(*p)(int,int), inta, int b)
- {
- Int temp;
- temp = (*p)(a, b);
- if(temp != 0)
- return OK;
- else
- return FAIL;
- }
复制代码这样修改test函数,然后封装起来,test函数只做结果是否不为0的判断,后期开发人员可以把计算函数指针,和参与计算的两个参数输入给test,test就能返回OK或者FAIL。虽然这个test函数已经固定了,但后期开发人员依然可以随便更改计算函数。
下面是本文的pdf文档
回调函数的理解.pdf
(445.58 KB, 下载次数: 64)
作者: cyhauxiang 时间: 2019-6-21 01:30
讲的很好,谢谢!
作者: chenyh85 时间: 2019-11-23 16:20
很好,听懂了~~~
作者: williamfang 时间: 2019-12-18 16:12
很好,清晰易懂,谢谢!上面第二步:实例解释,代码中第21行temp = test(sub, a, b);应该是笔误,应该是temp = test(mul, a, b);
作者: IdeaMing 时间: 2020-4-16 09:27
确实是写错了,谢谢提醒,已经无法修改了,希望后面读者注意一下。
作者: 淡定120 时间: 2020-8-20 14:26
很好,清晰易懂!
作者: ozp2003 时间: 2020-11-17 15:05
这几天刚接触STM32的HAL库,刚知道回调函数,我的理解就是中断或者别的执行的时候,通过函数指针调用回调函数,然后返回,查网上的理解是方便后期开发人员在调用的回调函数中开发!但是又冒出新疑问,网上解释说回调函数是并行的,其实回调函数与并行与否无关系,仅仅是用了函数指针,楼主的例子也可以说明,不存在是否并行!那么HAL库的说法是并行的,那么问题来了,进入中断后清了中断标志,假设执行回调函数的时候,外部又触发了中断咋办?外面排队还是又触发中断,理论上说,清了标志位,那就可以再次中断了~~
作者: sj904 时间: 2020-11-18 11:39
刚学了复杂声明就看到楼主的贴子,很是受益,书上是这么说的,因为函数不能直接做形参,所以要在形参里调用函数时,要用指针的方式。
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |