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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【C/C 】浅谈C/C 中函数指针与回调函数

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

01、函數指針

1.1、函數指針定義

一個函數總是占用一段連續的內存區域,函數名在表達式中有時也會被轉換為該函數所在內存區域的首地址,這和數組名非常類似。我們可以把函數的這個首地址(或稱入口地址)賦予一個指針變量,使指針變量指向函數所在的內存區域,然后通過指針變量就可以找到并調用該函數。這種指針就是函數指針。

簡言之:函數指針其實就是一個指針變量,代表著一段內存。

1.2、函數指針的定義形式

returnType (*pointerName)(param list);

returnType 為函數返回值類型,pointerName 為指針名稱,param list 為函數參數列表。參數列表中可以同時給出參數的類型和名稱,也可以只給出參數的類型,省略參數的名稱,這一點和函數原型非常類似。

返回類型(*函數名)(參數表)

例如下面兩種寫法都是正確的。

「寫法一:」

void (*F_TYPE)(int nParam,char strName); //帶參數變量名

「寫法二:」

void (*F_TYPE)(int,char); //不帶參數變量名

注意事項:注意( )的優先級高于*,第一個括號不能省略,如果寫作returnType pointerName(param list);就成了函數原型,它表明函數的返回值類型為returnType*

1.3、函數指針與typedef

想必大家都能看出來,函數指針的定義是很長一段的,如果每次是用都要寫這么長一段,額,大可不必,因為,typedef能夠解決這個問題。

typedef:程序中的作用一般是取別名,例如下面這個例子,我們把函數指針換個名字。

typedef 返回類型(*新類型)(參數表)

//1.默認原始寫法: void?callbackint(int?a,?int?b,?int?(*pMsg)(int?a,int?b));? //2.typedef優化后: typedef?void?(*PSM)(int?a,?int?b); void?callbackint(int?a,?int?b,?PSM?p);

這樣做的好處是,以后只要需要使用int (*pMsg)(int a, int b)的地方我們都能使用PSM p這種方式來替換他。

typedef是C語言基礎,這里不浪費時間在關鍵字上面,感興趣的可以自行了解一下。

02、回調函數

2.1、回調函數定義

百度給的解釋是:

回調函數就是一個被作為參數傳遞的函數。在C語言中,回調函數只能使用函數指針實現,在C 、Python、ECMAscript等更現代的編程語言中還可以使用仿函數或匿名函數。回調函數的使用可以大大提升編程的效率,這使得它在現代編程中被非常多地使用。同時,有一些需求必須要使用回調函數來實現。最著名的回調函數調用有C/C 標準庫stdlib.h/cstdlib中的快速排序函數qsort和二分查找函數bsearch中都會要求的一個與strcmp類似的參數,用于設置數據的比較方法。

關于名詞仿函數,請參考STL源碼剖析中的算法一塊兒,會有非常細致的解釋。

我自己的理解就是:通過參數將函數地址傳入,在多線程中,如果主線程在執行此函數時,通過參數中的函數地址,相當于異步執行了另外一個函數,另外一個函數也就是我們所稱的回調函數,回調函數多用于socket、http等協議中的消息交互處理,回調函數的本質就是C/C 中的函數指針,如上所述。

2.2、回調函數的使用場景

著名的 lone wolf 曾經解釋過這個問題:

其實回調就是一種利用函數指針進行函數調用的過程. 為什么要用回調呢?比如我要寫一個子模塊給你用, 來接收遠程socket發來的命令.當我接收到命令后, 需要調用你的主模塊的函數, 來進行相應的處理.但是我不知道你要用哪個函數來處理這個命令, 我也不知道你的主模塊是什么.cpp或者.h, 或者說, 我根本不用關心你在主模塊里怎么處理它, 也不應該關心用什么函數處理它…… 怎么辦? 使用回調!

什么是回調函數?

回調函數是應用程序提供給Windows系統DLL或其它DLL調用的函數,一般用于截獲消息、獲取系統信息或處理異步事件。應用程序把回調函數的地址指針告訴DLL,而DLL在適當的時候會調用該函數。回調函數必須遵守事先規定好的參數格式和傳遞方式,否則DLL一調用它就會引起程序或系統的崩潰。通常情況下,回調函數采用標準WindowsAPI的調用方式,即__stdcall,當然,DLL編制者可以自己定義調用方式,但客戶程序也必須遵守相同的規定。在__stdcall方式下,函數的參數按從右到左的順序壓入堆棧,除了明確指明是指針或引用外,參數都按值傳遞,函數返回之前自己負責把參數從堆棧中彈出。理解回調函數!

在很多第三方庫中,比如libcurl中:

CURL_EXTERN curl_easy_setopt(CURL* curl,CURLoption option, ...);

就是用了回調函數,通過設置一個函數地址,當我們將內容發送到http請求頁面之后,頁面會通過字節流返回一個stringstream類型數據,里面就是我們請求服務器之后的返回結果,在一些頻繁請求中,你不可能做到每一個都要程序停下來處理,這個時候,就可以使用回調函數來處理,異步通訊。

多線程中:主線程收發數據、子線程處理響應數據。大致都是一個意思。

03、實例重釋

我這里分文件舉一個簡單的例子闡述剛才上面說到的內容。可能內容不夠精煉,大佬請隨意,初學者建議看一下,很好理解。

功能:創建一個函數,傳遞兩個int類型參數,通過回調函數返回其兩個int類型參數的計算結果。

CallBack.h內容如下:

#ifndef?_CALLBACK_H #define?_CALLBACK_H//使用typedef進行簡化代碼,按部就班的寫肯定沒問題 typedef?int?(*PMSGMessage)(int?a,?int?b);//回調函數 int?callbackInt(int?a,?int?b,?PMSGMessage?p);?#endif

CallBack.cpp內容如下:

#include? #include?"CallBack.h"using?namespace?std;int?callbackInt(int?a?,int?b,?PMSGMessage?p) {//回調函數實現retrun?p(a,b) }

test.cpp函數內容如下:

#include? #include?"CallBack.h" using?namespace?std;int?Multiplication(int?a,?int?b) {//參數檢查(避免出現0)if(?a?==?0?||?b?==?0){cout?<<?"其中有參數為0,結果應避免為0"?<<?endl;return?0;}return?a?*?b; }int?main() {int?n?=?6;int?m?=?11;int?bRet?=?callbackInt(n,m,add);//如果我們用了類,就是函數等都是成員函數,我們這里要帶上域操作符("?::?")cout?<<?"回調函數執行的結果是:"?<<?bRet?<<?endl;?system("pause");return?0; }

小結:回調函數的簡單應用大概就是這么多,如果有機會,建議多用點開源庫,那里面很多地方都是用了回調函數機制,而且都是比此例子高級一點的用法,但是基本思想都一樣,不要因為用法高級一點就害怕了,自己寫兩個例子之后,想必對于回調會有更深的理解。

來源:

https://blog.csdn.net/m0_43458204/article/details/116715045

總結

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

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