函数指针与回调函数详解

函数指针回调函数详解

1.什么是函数指针?

函数(的)指针就是指针。这个指针存放一个函数的地址,而函数的名称就该函数的入口,即地址。这类似于数组名就是数组的首地址。我们可以通过反汇编直观的查看到函数名和函数地址的关系。

080483c4 <rfun>:80483c4:       55                      push   %ebp80483c5:       89 e5                   mov    %esp,%ebp80483c7:       83 ec 28                sub    $0x28,%esp······80483f3:       e8 cc ff ff ff          call   80483c4 <rfun>······

第一行080483c4就是函数在内存中的地址,后面的 rfun 就是函数名,还可以看出第二行和第一行的地址相同,所以可以知道函数名就是该函数的入口地址。 
第6行的call 80483c4 rfun就是再次调用这个函数,回到这个函数的入口出执行,可以看出该函数是一个递归函数。

2.函数指针的使用

2.1调用函数

我们就用函数指针调用刚才的rfun函数。

int rfun(unsigned x);//函数的声明

通过函数的声明,可以得到rfun函数的返回值类型,参数类型和参数个数。这些都是定义指针函数的必要条件!既然函数名就是函数地址,我们就可以用一个指针指向它,函数指针如下:

int (*pfun)(unsigned);//函数指针的定义
pfun = rfun;//函数指针的初始化

pfun就是指针变量,可以直接用函数名rfun赋值给pfun这个指针。函数指针在调用时和函数调用一致,只是用指针代替了函数名。

pfun(x);//函数指针的调用

函数指针不能自增和自减操作,否则程序会崩溃。

2.2作为函数的参数

函数指针作为A函数的参数,A函数称为回调函数。A函数的定义为:

int rfun_call(int (*pfun)(unsigned), unsigned x)
{return pfun(x);
}

这个函数的第一个参数是一个返回值为int类型,参数为一个且是unsigned类型函数的指针,第二个参数是 unsigned类型。

3.什么是回调函数?

回调函数(Callback Functions)就是一个通过函数指针调用的函数。

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。刚才的rfun_call就是一个回调函数。这个函数是自己写的,下面就用系统感受一下的回调函数。

先说明两个Linux系统函数,一个是alarm函数,一个是signal函数

①alarm函数,也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号。

#include <unistd.h>//alarm的头文件
unsigned int alarm(unsigned int seconds);//alarm的函数原型

②signal函数,执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。

#include <signal.h>//signal函数的头文件typedef void (*sighandler_t)(int);//sighandler_t是一个指向返回值为void,参数为int的函数指针
sighandler_t signal(int signum, sighandler_t handler);//signal函数的原型

描述一个场景: 
你要睡觉,只睡2秒,所以你定了一个2秒的闹钟,到第3秒时,闹钟给你发信号,说时间到了

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void fun(int signum)
{printf("时间到了,起床!\n");
}int main()
{int i;alarm(3);//定2秒闹钟,第3秒会响铃,也就是发信号signal(SIGALRM, fun);//接收闹铃的信号,去执行fun()for(i = 0; i < 3; i++){sleep(1);//描述时间的流逝printf("%d秒过去了\n", i+1);}printf("睡觉结束");return 0;
}

执行结果如下:

[root@menwen-linux test]# ./callback
1秒过去了
2秒过去了
时间到了,起床!
3秒过去了
睡觉结束

在时间到第三秒的时候,signal函数执行了fun函数,执行完fun函数,就会继续执行“睡觉结束”。 
如果不设置闹铃(注释alarm(3)),程序就会一直按顺序执行,直到程序结束,永远不会执行回调函数。 
signal函数就是一个回调函数,接收一个函数指针,和一个信号量SIGALRM,在Linux内核代码中,SIGALRM等信号其实是一堆宏定义,都对应一个数值

#define SIGHUP           1
#define SIGINT           2
#define SIGQUIT          3
#define SIGILL           4
......
#define SIGPIPE         13
#define SIGALRM         14
#define SIGTERM         15
#define SIGSTKFLT       16
#define SIGCHLD         17
等等.....

或者命令行输入kill -l 也会对应出现这个信号量。

[menwen@menwen-linux 6th_day]$ kill -l1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
......
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。我们实现了fun函数,而我们不调用该函数,而是去睡觉(或者干其他事),等到时间到,回调函数就会去响应,这是一种系统异步处理的机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转载】Direct3D基础知识

原文&#xff1a;Direct3D基础知识 重新从头开始学习DX,以前太急于求成了,很多基础知识都没掌握就开始写程序了,结果出了问题很难解决.1. D3D体系结构D3D与GDI处与同一层次,区别在于,D3D可以使用HAL(Hardware Abstraction Layer)通过DDI来访问图形硬件,充分发挥硬件性能.…

翻译:程序员数据结构基础:选择正确的数据结构

本文转载自GameDev.net&#xff0c;仅供学习交流。因为刚刚开始学习翻译&#xff0c;难免有些疏漏&#xff0c;如果有哪些地方翻译的不正确&#xff0c;请不吝告知&#xff0c;万分感谢。 原文链接&#xff1a;http://www.gamedev.net/page/resources/_/technical/general-prog…

关于Xcode隐藏打印的logs的方法

https://www.cnblogs.com/jukaiit/p/5881062.html 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 添加参数&#xff1a; Name &#xff1a;OS_ACTIVITY_MODE Value : disable

指针函数与函数指针的区别

首先它们之间的定义&#xff1a;1、指针函数是指带指针的函数&#xff0c;即本质是一个函数&#xff0c;函数返回类型是某一类型的指针。 类型标识符 *函数名(参数表)int *f(x&#xff0c;y);首先它是一个函数&#xff0c;只不过这个函数的返回值是一个地址值。函数返回值必须用…

数组字典

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {autoreleasepool { //把字典放到数组中NSDictionary *dic1{"name":"小明","class":"IOS8","age":"22"};NSDictionary *dic2{&…

C++走向远洋——63(项目二2、两个成员的类模板)

*/ * Copyright (c) 2016&#xff0c;烟台大学计算机与控制工程学院 * All rights reserved. * 文件名&#xff1a;text.cpp * 作者&#xff1a;常轩 * 微信公众号&#xff1a;Worldhello * 完成日期&#xff1a;2016年6月4日 * 版本号&#xff1a;V1.0 * 问题描述&…

iOS 抓包工具 charles工具

在Charles官网下载最新的 安装包 在电脑上安装完成之后&#xff0c;以 注册码 Registered Name: https://zhile.io License Key: 48891cf209c6d32bf4 进行注册即可完成 在手机上面设置代理&#xff1a;输入电脑的网络IP以及端口号 以下为查找的步骤&#xff1a; 在手机上手…

指针数组与数组指针详解

指针数组与数组指针详解 1.什么是指针数组和数组指针&#xff1f; 指针数组&#xff1a;指针数组可以说成是”指针的数组”&#xff0c;首先这个变量是一个数组&#xff0c;其次&#xff0c;”指针”修饰这个数组&#xff0c;意思是说这个数组的所有元素都是指针类型&#xff0…

写一个Android输入法01——最简步骤

本文演示用Android Studio写一个最简单的输入法。界面和交互都很简陋&#xff0c;只为剔肉留骨&#xff0c;彰显写一个Android输入法的要点。 1、打开Android Studio创建项目&#xff0c;该项目和普通APP的不同之处在于它不需要添加任何Activity&#xff1a;我给该输入法命名为…

句柄与指针的区别

句柄实际上是一种指向某种资源的指针&#xff0c;但与指针又有所不同&#xff1a;指针对应着一个数据在内存中的地址&#xff0c;得到了指针就可以自由地修改该数据。 Windows并不希望一般程序修改其内部数据结构&#xff0c;因为这样太不安全。所以Windows给每个使用GlobalAll…

iOS 11 适配

http://blog.csdn.net/st646889325/article/details/79066361 这一个不错的文章

谈谈自己对于Auth2.0的见解

Auth的原理网上有很多&#xff0c;我这里就不在赘述了。 这里有张时序图我个人觉得是比较合理而且直观的&#xff0c;&#xff08;感谢这篇博文&#xff1a;http://justcoding.iteye.com/blog/1950270&#xff09; 参照这个流程&#xff0c;模拟了下部分代码&#xff0c;当然是…

某个时间点 几天后

1、某个时间点 3天后 NSDate *maxDate [NSDate dateWithTimeInterval:3 * 24 * 60 * 60 sinceDate:date];//3天后 2、现在 3天后 NSDate *minDate [[NSDate date] initWithTimeIntervalSinceNow:3 * 24 * 60 * 60];

iPad开发--QQ空间,处理横竖屏布局,实现子控件中的代理

一.主界面横竖屏效果图 二.主界面加载, 初始化Dock(红色框的控件),判断程序启动时的屏幕方向.调用自己- (void)transitionToLandScape:(BOOL)isLandScape;方法,通知子控件屏幕方向改变,将此事件一直传递下去程序运行过程中屏幕方向改变会调用- (void)viewWillTransitionToSize:…

C++ Vector 汇总

C vector erase函数最近使用了顺序容器的删除元素操作&#xff0c;特此记录下该函数的注意事项。 在Cprimer中对c.erase(p) 这样解释的&#xff1a;c.erase(p) 删除迭代器p所指向的元素&#xff0c;返回一个指向被删元素之后元素的迭代器&#xff0c;若p指向尾元素&#xff…

vNext之旅(2):net451、dotnet5.4、dnx451、dnxcore50都是什么鬼

继上次”vNext之旅&#xff08;1&#xff09;&#xff1a;从概念和基础开始”之后再次学习vNext重新遇到了弄不懂的事情&#xff0c;花了一些时间学习&#xff0c;今天来分享一下&#xff0c;为后人节省些时间。起因 在用vNext造轮子——框架的时候引入“Microsoft.Dnx.Runtime…

C++中模板使用详解

转自&#xff1a;http://www.360doc.com/content/09/0403/17/799_3011262.shtml 1. 模板的概念。 我们已经学过重载(Overloading)&#xff0c;对重载函数而言,C的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如&#xff0c;为求两个数的最大值&#xf…

腾讯2016春招安全岗笔试题解析

腾讯2016春招安全岗笔试题解析 昨天&#xff08;4月2日&#xff09;晚上7:00到9:00做了腾讯春招安全岗的笔试题。下面解析一下&#xff1a; 题目解析 1 在生成随机数前用当前时间设置随机数种子应该是安全的。如果程序用固定的数产生随机数&#xff0c;其结果也是固定的。如果用…

网络请求数据解析时,判断数据是否为空

//判断是否为空 (BOOL)IsStringEmptyOrNull:(NSString *)str { if (!str) { // null object return true; }else if (str nil){ return true; }else { if ([str isKindOfClass:[NSNull class]]) { return true; …

VS项目属性的一些配置项的总结(持续增加。。。)

首先&#xff0c;解决方案和项目文件夹包含关系(c项目)&#xff1a; VS解决方案和各个项目文件夹以及解决方案和各个项目对应的配置文件包含关系&#xff1a;假设新建一个项目ssyy&#xff0c;解决方案起名fangan&#xff0c;注意解决方案包括项目&#xff0c;此时生成的最外层…