函数指针与回调函数详解
函數(shù)指針與回調(diào)函數(shù)詳解
1.什么是函數(shù)指針?
函數(shù)(的)指針就是指針。這個指針存放一個函數(shù)的地址,而函數(shù)的名稱就該函數(shù)的入口,即地址。這類似于數(shù)組名就是數(shù)組的首地址。我們可以通過反匯編直觀的查看到函數(shù)名和函數(shù)地址的關(guān)系。
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就是函數(shù)在內(nèi)存中的地址,后面的 rfun 就是函數(shù)名,還可以看出第二行和第一行的地址相同,所以可以知道函數(shù)名就是該函數(shù)的入口地址。?
第6行的call 80483c4 rfun就是再次調(diào)用這個函數(shù),回到這個函數(shù)的入口出執(zhí)行,可以看出該函數(shù)是一個遞歸函數(shù)。
2.函數(shù)指針的使用
2.1調(diào)用函數(shù)
我們就用函數(shù)指針調(diào)用剛才的rfun函數(shù)。
int rfun(unsigned x);//函數(shù)的聲明通過函數(shù)的聲明,可以得到rfun函數(shù)的返回值類型,參數(shù)類型和參數(shù)個數(shù)。這些都是定義指針函數(shù)的必要條件!既然函數(shù)名就是函數(shù)地址,我們就可以用一個指針指向它,函數(shù)指針如下:
int (*pfun)(unsigned);//函數(shù)指針的定義 pfun = rfun;//函數(shù)指針的初始化pfun就是指針變量,可以直接用函數(shù)名rfun賦值給pfun這個指針。函數(shù)指針在調(diào)用時和函數(shù)調(diào)用一致,只是用指針代替了函數(shù)名。
pfun(x);//函數(shù)指針的調(diào)用函數(shù)指針不能做自增和自減操作,否則程序會崩潰。
2.2作為函數(shù)的參數(shù)
函數(shù)指針作為A函數(shù)的參數(shù),A函數(shù)稱為回調(diào)函數(shù)。A函數(shù)的定義為:
int rfun_call(int (*pfun)(unsigned), unsigned x) {return pfun(x); }這個函數(shù)的第一個參數(shù)是一個返回值為int類型,參數(shù)為一個且是unsigned類型函數(shù)的指針,第二個參數(shù)是 unsigned類型。
3.什么是回調(diào)函數(shù)?
回調(diào)函數(shù)(Callback Functions)就是一個通過函數(shù)指針調(diào)用的函數(shù)。
如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。剛才的rfun_call就是一個回調(diào)函數(shù)。這個函數(shù)是自己寫的,下面就用系統(tǒng)感受一下的回調(diào)函數(shù)。
先說明兩個Linux系統(tǒng)函數(shù),一個是alarm函數(shù),一個是signal函數(shù)
①alarm函數(shù),也稱為鬧鐘函數(shù),它可以在進程中設置一個定時器,當定時器指定的時間到時,它向進程發(fā)送SIGALRM信號。
#include <unistd.h>//alarm的頭文件 unsigned int alarm(unsigned int seconds);//alarm的函數(shù)原型②signal函數(shù),執(zhí)行了signal()調(diào)用后,進程只要接收到類型為sig的信號,不管其正在執(zhí)行程序的哪一部分,就立即執(zhí)行func()函數(shù)。當func()函數(shù)執(zhí)行結(jié)束后,控制權(quán)返回進程被中斷的那一點繼續(xù)執(zhí)行。
#include <signal.h>//signal函數(shù)的頭文件typedef void (*sighandler_t)(int);//sighandler_t是一個指向返回值為void,參數(shù)為int的函數(shù)指針 sighandler_t signal(int signum, sighandler_t handler);//signal函數(shù)的原型描述一個場景:?
你要睡覺,只睡2秒,所以你定了一個2秒的鬧鐘,到第3秒時,鬧鐘給你發(fā)信號,說時間到了
執(zhí)行結(jié)果如下:
[root@menwen-linux test]# ./callback 1秒過去了 2秒過去了 時間到了,起床! 3秒過去了 睡覺結(jié)束在時間到第三秒的時候,signal函數(shù)執(zhí)行了fun函數(shù),執(zhí)行完fun函數(shù),就會繼續(xù)執(zhí)行“睡覺結(jié)束”。?
如果不設置鬧鈴(注釋alarm(3)),程序就會一直按順序執(zhí)行,直到程序結(jié)束,永遠不會執(zhí)行回調(diào)函數(shù)。?
signal函數(shù)就是一個回調(diào)函數(shù),接收一個函數(shù)指針,和一個信號量SIGALRM,在Linux內(nèi)核代碼中,SIGALRM等信號其實是一堆宏定義,都對應一個數(shù)值
或者命令行輸入kill -l 也會對應出現(xiàn)這個信號量。
[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回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應。我們實現(xiàn)了fun函數(shù),而我們不調(diào)用該函數(shù),而是去睡覺(或者干其他事),等到時間到,回調(diào)函數(shù)就會去響應,這是一種系統(tǒng)異步處理的機制。
總結(jié)
以上是生活随笔為你收集整理的函数指针与回调函数详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓学习日志 Day15 — 数据库基础
- 下一篇: MFC CPropertySheet 多