為什麼 Windows API 使用 stdcall 調用約定?


你是想問為啥Windows C++中全是stdcall或WINAPI,而不是cdecl的calling convention吧?原因簡單直接,生成執行碼的大小。

WINAPI就是stdcall的一個宏定義,其實是一回事。stdcall約定是被調用者清棧,返回時指令帶一個退棧參數就可以了,被調用者自己一句ret n就完事了。

cdecl約定是調用者清棧,就是每一個調用者在函數調用完成後,要每一個調用者自己去拉esp把棧狀況改回來。

stdcall的缺點就是無法支持可變數量的參數,因為被調用者必須確定參數數量才能自己清棧。我印象中老Win32 API只有一個API支持變長參數,所以只有她是cdel而不是stdcall,來自user32的wsprintf。


省點內存唄,棧頂指針彈回這個指令,只需要函數實現一下,而不需要每一次調用結束都去實現一下。

當年從dos640k時代走出來的那堆微軟程序員,對於節省內存有各種變態手段。啟動階段想方設法不載入com組件,實在扛不住了就做一個超級精簡版com。更不用說MFC裡面的各種變態省內存方法了。


僅有的兩個回答都是非常正確的,不過我補充一點,Windows API使用stdcall是個歷史遺留的產物,要知道早期,NT3.1那時候的內存是非常寶貴的,所以使用stdcall可以顯著節約內存。(沒記錯的話張銀奎老師翻譯的《觀止:微軟創建NT和未來的奪命狂奔》提到過這個問題)


可能是因為dll,win32的api基本上都位於dll中,用stdcall比cdecl有一個優勢,清理堆棧的責任歸被調用者,因此這部分代碼存在於dll內部,一份代碼被多次使用,「大幅度」的減少了代碼量。

到了64位階段,這點節約也無所謂了,因此cdecl和stdcall被統一了


學彙編就什麼都知道了


推薦閱讀:

c++中的字元串常量為什麼可以賦值給char*?
我想自己用C/C++做一個腳本語言解釋器,但是不知道需要什麼知識?
c語言中實際上不存在賦值語句?
為什麼GCC會把0xBE-0x33解釋為浮點數?
c語言中指針指向的非指針變數不能使用++或--嗎?

TAG:C編程語言 | C | Windows開發 | Win32API |