callback用法简介
源地址:https://argcv.com/articles/2669.c
callback,函数的回调,从ANSI C开始,一直被广为使用。无论是windows API的所谓消息机制,动态链接库的调用,还是sqlite的命令,gcc下的pthread,qsort。callback都在其中起着难以替代的作用。
那么,callback为何如此受到亲睐呢?因为它可以以一个函数为参数,放到参数列表交给API,让API调用。比如有个文件夹下有一千万个文件,我们希望对每个文件进行一些处理,比如查看文件长度是否超过512字节。而遍历这个文件夹的程序是个API。如果不使用callback,API可能有两种办法,一种是申请一个超巨大的空间,然后把找到的所有文件名都放进去,然后返回这个空间(类似的还有把这组文件名写到文件中,一个意思),这样速度的确很快,而且简单方便,但问题是,一千万个文件,占用的空间是如此的庞大,空间复杂度为O(n),而我们只是要对每个文件进行一点小小的处理而已,实在是杀鸡焉用宰牛刀。另一个方法是搞个迭代器,每次只返回一个文件名,下次调用再返回下个。为了线程安全,每次传参都得来个指针之类的记录自己的进度。如果做的细心,也可以做的很快,也不占用空间。但问题是,只是个简单的遍历文件夹的API,这么折腾好累哦。而如果使用callback,事情就简单很多了。主程序调用API,把处理文件的函数用参数的方法传递给API,API每找到一个文件名,就调用这个函数,当场处理不用存储任何文件名。这样空间复杂度是O(1),而且方便有效,何乐而不为呢?
callback具体怎么实现的呢?我在本文中做一个小小的demo。
Demo的实现的功能是这样的:
bar.c调用foo.c的一个函数,请求给一个magic number。但foo.c的函数并不是直接返回,而是调用bar.c传递过来的函数use_magic_num,把magic number 作为参数使用进去。
首先,定义最后要被调用的函数use_magic_num如下:
1
2
3
4
5
6
|
void use_magic_num( int magic_num); void use_magic_num( int magic_num) { printf ( "bar.c : magic number is %d \n" , magic_num); } |
也就是传进去一个参数,然后函数会打印出这个magic number。它被放置在bar.c下
然后foo.h中定义API get_magic_num的原型
1
|
void get_magic_num( void (*callback)( int magic)); |
它的参数列表和普通的有点区别,传入的是一个函数指针,这个函数必须是原型为有一个int类型为参数,返回为void。其他的就和普通的函数一样了。
对get_magic_num进行实现。
1
2
3
4
5
6
7
|
typedef void (*foo_run_magic)( int ); void get_magic_num(foo_run_magic foo) { int magic = 9; foo(magic); } |
我么可以看到,在这儿,我做了点小花招,我typedef了这个函数指针,这样我们可以直接使用foo_run_magic来代替麻烦的各种括号的函数指针了。
然后调用 foo,其实就是调用传入的参数。在本工程中,也就是前面写的use_magic_num了。
虽然foo.c完全看不见use_magic_num,但完全不妨碍函数的使用。
最后定义bar.c的主程序
1
2
3
4
5
|
int main( int argc, char *argv[]) { get_magic_num(use_magic_num); return 0; } |
也就是调用foo并传入use_magic_num的函数了。
编译和执行结果大致是如下的样子:
1
2
3
4
5
6
7
|
[yu@argcv callback]$ make gcc -c -Wall -std=c99 bar.c -o bar.o gcc -c -Wall -std=c99 foo.c -o foo.o gcc -Wall -std=c99 -o bar bar.o foo.o [yu@argcv callback]$ ./bar bar.c : magic number is 9 [yu@argcv callback]$ |
完整的工程请参考此处
callback用法简介的更多相关文章
- IOS NSInvocation用法简介
IOS NSInvocation用法简介 2012-10-25 19:59 来源:博客园 作者:csj007523 字号:T|T [摘要]在 iOS中可以直接调用某个对象的消息方式有两种,其中一种就是 ...
- JodaTime用法简介
JodaTime用法简介 Java的Date和Calendar用起来简直就是灾难,跟C#的DateTime差距太明显了,幸好有JodaTime 本文简单罗列JodaTime的用法 package co ...
- Apache自带压力测试工具ab用法简介
ab命令原理 ab命令会创建很多的并发访问线程,模拟多个访问者同时对某一URL进行访问.它的测试目标是基于URL的,因此,既可以用来测试Apache的负载压力,也可以测试nginx.lighthttp ...
- Postman用法简介
转自:http://blog.csdn.net/flowerspring/article/details/52774399 Postman用法简介 转载 2016年10月10日 09:04:10 10 ...
- MSSQL Sql加密函数 hashbytes 用法简介
转自:http://www.maomao365.com/?p=4732 一.mssql sql hashbytes 函数简介 hashbytes函数功能为:返回一个字符,通过 MD2.MD4.MD5. ...
- java assert的用法简介【转】
assert的基本用法 assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制,如C,C++和Eiffel等,但是支持的形式不尽相同,有的是通过语言本身.有的是通过库 ...
- glVertexAttribPointer 用法简介
在内存中采用交叉模式存储,向gpu传入顶点数据的方法 GPU: #version 100 attribute highp vec2 aPosition; attribute highp vec2 a ...
- C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介
C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介 IP是一种普遍应用于因特网.允许不同主机能够相互找到对方的寻址协议.IP地址由4个十进制的数字号码所组成, ...
- Postman用法简介----https://blog.csdn.net/flowerspring/article/details/52774399
https://blog.csdn.net/flowerspring/article/details/52774399 Postman用法简介
随机推荐
- ASP.NET给Table动态添加删除行,并且得到控件的值
ASP.NET给Table动态添加控件并且得到控件的值 由于跟老师做一个小的项目,可是我自己又不太懂js,所以一直为动态建立表格并且能动态的取值和赋值感到苦恼.起初在网上找到了一些js资源,解决了动态 ...
- iphone开发,模拟器生成文件路径
原文链接:http://blog.csdn.net/gf771115/article/details/7722023 Finder---位置----apple(用户名)---application s ...
- javascript每日一练(十一)——多物体运动
一.多物体运动 需要注意:每个运动物体的定时器作为物体的属性独立出来互不影响,属性与运动对象绑定,不能公用: 例子1: <!doctype html> <html> <h ...
- QTabWidget 实现类似QQ聊天窗口(拖动分离出新的窗口)
新版本的QQ聊天窗口可以实现拖动,分离出新的窗口.浏览器等软件也可以实现类似操作.所以心血来潮想用Qt实现类似的功能.想用QTabWidget直接实现是很难的,仔细阅读源码,发现QTabWidget内 ...
- MUI 列表页面绑定接口数据
1.我们先看效果 2.功能分析 主要分为3步 数据初始化 下拉刷新 上拉加载 接口数据示例: { "List": [ { "Id": 9, "Orde ...
- ARMv8 Linux内核源代码分析:__flush_dcache_all()
1.1 /* * __flush_dcache_all() * Flush the wholeD-cache. * Corrupted registers: x0-x7, x9-x11 */ EN ...
- Spring注入静态变量(转)
今天碰到一个问题,我的一个工具类提供了几种静态方法,静态方法需要另外一个类的实例提供处理,因此就写出了这样的代码: Class Util{ private static XXX xxx; xxx = ...
- anglehack参赛总结
自已不足的方面: 自已和伙伴是带着idea去的,但是没有带有很大的热情激励和吸引在场的hacker加入团队,一定要找最优秀的人加入团队,事实上我是有这方面识人认人的能力的,24h,5-6个人的优秀团队 ...
- 基于Tire树和最大概率法的中文分词功能的Java实现
对于分词系统的实现来说,主要应集中在两方面的考虑上:一是对语料库的组织,二是分词策略的制订. 1. Tire树 Tire树,即字典树,是通过字串的公共前缀来对字串进行统计.排序及存储的一种树形结构 ...
- 《C陷阱与缺陷》整理二
1.数组名作实參 在C语言中,我们没有办法将一个数组作为函数參数传递,假设我们使用数组名作为參数.这个时候数组名立马会被转换为指向该数组的第一个元素的指针. 关于这一点的理解能够向前深 ...