__stdcall、__cdcel和__fastcall三者的區(qū)別

__stdcall、__cdecl和__fastcall是三種函數(shù)調(diào)用協(xié)議,函數(shù)調(diào)用協(xié)議會(huì)影響函數(shù)參數(shù)的入棧方式、棧內(nèi)數(shù)據(jù)的清除方式、編譯器函數(shù)名的修飾規(guī)則等。如下圖所示,可以在IDE環(huán)境中設(shè)定所有函數(shù)默認(rèn)的調(diào)用協(xié)議,還可以在函數(shù)定義時(shí)單獨(dú)設(shè)定本函數(shù)的調(diào)用協(xié)議。

調(diào)用協(xié)議常用場(chǎng)合

__stdcall:Windows API默認(rèn)的函數(shù)調(diào)用協(xié)議。

__cdecl:C/C++默認(rèn)的函數(shù)調(diào)用協(xié)議。

__fastcall:適用于對(duì)性能要求較高的場(chǎng)合。

函數(shù)參數(shù)入棧方式

__stdcall:函數(shù)參數(shù)由右向左入棧。

__cdecl:函數(shù)參數(shù)由右向左入棧。

__fastcall:從左開始不大于4字節(jié)的參數(shù)放入CPU的ECX和EDX寄存器,其余參數(shù)從右向左入棧。

問題一:__fastcall在寄存器中放入不大于4字節(jié)的參數(shù),故性能較高,適用于需要高性能的場(chǎng)合。

棧內(nèi)數(shù)據(jù)清除方式

__stdcall:函數(shù)調(diào)用結(jié)束后由被調(diào)用函數(shù)清除棧內(nèi)數(shù)據(jù)。

__cdecl:函數(shù)調(diào)用結(jié)束后由函數(shù)調(diào)用者清除棧內(nèi)數(shù)據(jù)。

__fastcall:函數(shù)調(diào)用結(jié)束后由被調(diào)用函數(shù)清除棧內(nèi)數(shù)據(jù)。

問題一:不同編譯器設(shè)定的棧結(jié)構(gòu)不盡相同,跨開發(fā)平臺(tái)時(shí)由函數(shù)調(diào)用者清除棧內(nèi)數(shù)據(jù)不可行。

問題二:某些函數(shù)的參數(shù)是可變的,如printf函數(shù),這樣的函數(shù)只能由函數(shù)調(diào)用者清除棧內(nèi)數(shù)據(jù)。

問題三:由調(diào)用者清除棧內(nèi)數(shù)據(jù)時(shí),每次調(diào)用都包含清除棧內(nèi)數(shù)據(jù)的代碼,故可執(zhí)行文件較大。

C語言編譯器函數(shù)名稱修飾規(guī)則

__stdcall:編譯后,函數(shù)名被修飾為“_functionname@number”。

__cdecl:編譯后,函數(shù)名被修飾為“_functionname”。

__fastcall:編譯后,函數(shù)名給修飾為“@functionname@nmuber”。

注:“functionname”為函數(shù)名,“number”為參數(shù)字節(jié)數(shù)。

注:函數(shù)實(shí)現(xiàn)和函數(shù)定義時(shí)如果使用了不同的函數(shù)調(diào)用協(xié)議,則無法實(shí)現(xiàn)函數(shù)調(diào)用。

C++語言編譯器函數(shù)名稱修飾規(guī)則

__stdcall:編譯后,函數(shù)名被修飾為“?functionname@@YG******@Z”。

__cdecl:編譯后,函數(shù)名被修飾為“?functionname@@YA******@Z”。

__fastcall:編譯后,函數(shù)名被修飾為“?functionname@@YI******@Z”。

注:“******”為函數(shù)返回值類型和參數(shù)類型表。

注:函數(shù)實(shí)現(xiàn)和函數(shù)定義時(shí)如果使用了不同的函數(shù)調(diào)用協(xié)議,則無法實(shí)現(xiàn)函數(shù)調(diào)用。

C語言和C++語言間如果不進(jìn)行特殊處理,也無法實(shí)現(xiàn)函數(shù)的互相調(diào)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用。當(dāng)一個(gè)函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,665評(píng)論 1 19
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,354評(píng)論 0 6
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,200評(píng)論 30 471
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,865評(píng)論 0 27
  • 一:java概述:1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,686評(píng)論 0 11