__stdcall、__cdecl 、CALLBACK 几种函数修饰符
生活随笔
收集整理的這篇文章主要介紹了
__stdcall、__cdecl 、CALLBACK 几种函数修饰符
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
CALLBACK == WINAPI ==__stdcall
實際上就是一種調用模式,就是約定由調用函數來自行解決壓棧參數,同 pascal 調用。回調函數只能是類的靜態成員函數或是類外定義的全局函數
#define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall #define PASCAL __stdcall #define cdecl _cdecl #ifndef CDECL #define CDECL _cdecl #endif
WinMain函數是由系統調用的,Windows系統規定由系統調用的函數都遵守 PASCAL調用方式 。 但是VC中函數的缺省調用方式是__cdecl,也就是C調用方式 。 在Windows編程中將遇到很多聲明修飾符,如CALLBACK,WINAPI,PASCAL這些在 IntelCPU的計算機上都是__stdcall。 幾乎我們寫的每一個WINDOWS API函數都是__stdcall類型的,為什么? 首先,我們談一下兩者之間的區別:
注釋:
所謂的回調函數,就是說,當某一個事件發生時,系統會根據你給出的函數指針來調用你定義的這個回調函數,這是系統提供的一種和用戶通訊的方法。他通過調用用戶自定義的函數來給用戶提供一個處理消息或事件的機制。 回調函數并非Windows特有,只要象C/C++這樣支持函數指針的語言都有回調函數的概念,它實際上是向被調用函數傳一個你的函數地址,然后被調用函數向通過你傳入的函數地址來調用你的函數。比如你做了一個遍歷樹的函數,但你不知遍歷者將對各節點做何種處理時,你就可以在這個遍歷函數中加一個函數地址的參數,這樣調用者在遍歷該樹時就可以做各種有意義的工作了:比如打印各節點數據、匯總所有節點之類。 回調函數(CallBack Function)在windows編程中用到時,是由windows操作系統直接調用的,一般是在windows編程中的對各種事件的響應。在VC編程中不再采用回調函數了,而是采用了begin_messagemap,end_messagemap,它的作用和windows編程中的回調函數(CallBack Function)是一樣的。 回調函數(CallBack Function)就是函數指針的調用,看看關于函數指針的用法,了解了函數指針也就了解了CALLBACK。設計一個函數接口的參數是某一函數的指針,在設計的函數中調用該函數指針,那么該指針指向的函數就是callback functioin。回調函數是由你來編寫其功能實現,由Windows操作系統調用的函數。
轉自:http://wdtxslqnn.blog.163.com/blog/static/44246485201162911188753/ (向原作者致敬)
與50位技術專家面對面20年技術見證,附贈技術全景圖
實際上就是一種調用模式,就是約定由調用函數來自行解決壓棧參數,同 pascal 調用。回調函數只能是類的靜態成員函數或是類外定義的全局函數
#define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall #define PASCAL __stdcall #define cdecl _cdecl #ifndef CDECL #define CDECL _cdecl #endif
VC中主要有兩種函數調用方式:
- 一種是__stdcall;
- 另一種是__cdecl;
- 還有第三種 naked(自己編匯編控制堆棧)。
- 使用PASCAL調用方式,被調函數在返回到調用者之前將參數從棧中刪除。
- 使用C調用方式,參數的刪除是調用者完成的 。
WinMain函數是由系統調用的,Windows系統規定由系統調用的函數都遵守 PASCAL調用方式 。 但是VC中函數的缺省調用方式是__cdecl,也就是C調用方式 。 在Windows編程中將遇到很多聲明修飾符,如CALLBACK,WINAPI,PASCAL這些在 IntelCPU的計算機上都是__stdcall。 幾乎我們寫的每一個WINDOWS API函數都是__stdcall類型的,為什么? 首先,我們談一下兩者之間的區別:
__cdecl 和 __stdcall 的區別
windows的函數調用時需要用到棧(STACK,一種先入后出的存儲結構)。當函數調用完成后,棧需要執行清除操作,這里就是問題的關鍵,如何清除?
如果我們的函數使用了_cdecl,那么棧的清除工作是由調用者,用COM的術語來講就是客戶來完成的。這樣就帶來了一個棘手的問題,不同的編譯器產生棧的方式不盡相同,那么調用者能否正常的完成清除工作呢?答案是不能。
如果使用__stdcall,上面的問題就解決了,函數自己解決清除工作。所以,在跨(開發)平臺的調用中,我們都使用__stdcall(雖然有時是以WINAPI的樣子出現)。
那么為什么還需要_cdecl呢?當我們遇到這樣的函數如fprintf()它的參數是可變的,不定長的,被調用者事先無法知道參數的長度,事后的清除工作也無法正常的進行,因此,這種情況我們只能使用_cdecl。
到這里我們有一個結論,如果你的程序中沒有涉及可變參數,最好使用__stdcall關鍵字。
CALLBACK 關鍵字
- CALLBACK函數也稱為回調函數,是由你自己來設計,但是供windows調用的。如果你寫過SDK程序,就該知道WindowProc函數,它是你自己寫的,什么消息怎么處理,但是在程序中你并沒有去調用這個函數,因為不需要你自己調用,到了該調用的時候windows自然會去調用。如果你的函數不是回調函數,就不要用CALLBACK或者_cdecl來修飾。
- 如果你寫回調函數,而且它的參數所占的字節是不可變的,那么就用CALLBACK(大部分是這種情況),如果參數可能會變,那么就用_cdecl 。
注釋:
總結
以上是生活随笔為你收集整理的__stdcall、__cdecl 、CALLBACK 几种函数修饰符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 函数调用规范__cdecl和__stdc
- 下一篇: android有关医疗实现功能,基于An