_stdcall,_cdecl區別

轉自:點擊打開鏈接

(1) _stdcall調用
  _stdcall是Pascal程序的缺省調用方式,參數採用從右到左的壓棧方式,被調函數自身在返回前清空堆棧。
  WIN32 Api都採用_stdcall調用方式,這樣的宏定義說明了問題:

  #define WINAPI _stdcall

  按C編譯方式,_stdcall調用約定在輸出函數名前面加下劃線,後面加“@”符號和參數的字節數,形如。

(2) _cdecl調用
  _cdecl是C/C++的缺省調用方式,參數採用從右到左的壓棧方式,傳送參數的內存棧由調用者維護。_cedcl約定的函數只能被C/C++調用,每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。

  由於_cdecl調用方式的參數內存棧由調用者維護,所以變長參數的函數能(也只能)使用這種調用約定。關於C/C++中變長參數(…)的問題,筆者將另文詳述。

  由於Visual C++默認採用_cdecl 調用方式,所以VC中中調用DLL時,用戶應使用_stdcall調用約定。
  按C編譯方式,_cdecl調用約定僅在輸出函數名前面加下劃線,形如_functionname。

  (3) _fastcall調用
  _fastcall調用較快,它通過CPU內部寄存器傳遞參數。

  按C編譯方式,_fastcall調用約定在輸出函數名前面加“@”符號,後面加“@”符號和參數的字節數,形如@functionname@number。


幾乎我們寫的每一個WINDOWS API函數都是__stdcall類型的,爲什麼??
     首先,我們談一下兩者之間的區別:
       WINDOWS的函數調用時需要用到棧(STACK,一種先入後出的存儲結構)。當函數
調用完成後,棧需要清除,這裏就是問題的關鍵,如何清除??
       如果我們的函數使用了_cdecl,那麼棧的清除工作是由調用者,用COM的術語來講
就是客戶來完成的。這樣帶來了一個棘手的問題,不同的編譯器產生棧的方式不盡相同
,那麼調用者能否正常的完成清除工作呢?答案是不能。
       如果使用__stdcall,上面的問題就解決了,函數自己解決清除工作。所以,在跨
(開發)平臺的調用中,我們都使用__stdcall(雖然有時是以WINAPI的樣子出現)。
       那麼爲什麼還需要_cdecl呢?當我們遇到這樣的函數如fprintf()它的參數是可變
的,不定長的,被調用者事先無法知道參數的長度,事後的清除工作也無法正常的進行
,因此,這種情況我們只能使用_cdecl。
       到這裏我們有一個結論,如果你的程序中沒有涉及可變參數,最好使用__stdcal
l關鍵字
發佈了12 篇原創文章 · 獲贊 31 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章