函數指針與回調函數詳解

函數指針回調函數詳解

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.pswp.cn/news/458426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458426.shtml
英文地址,請注明出處:http://en.pswp.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;此時生成的最外層…