日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

函数指针与回调函数详解

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 函数指针与回调函数详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

函數指針回調函數詳解

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函數,而我們不調用該函數,而是去睡覺(或者干其他事),等到時間到,回調函數就會去響應,這是一種系統異步處理的機制。

總結

以上是生活随笔為你收集整理的函数指针与回调函数详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。