當(dāng)前位置:
首頁 >
函数调用约定
發(fā)布時間:2025/3/20
32
豆豆
函數(shù)調(diào)用約定
標(biāo)簽:? 函數(shù)? 調(diào)用? 約定? 2008-11-14 15:40 計算機提供了一種被稱為棧的數(shù)據(jù)結(jié)構(gòu)來支持參數(shù)傳遞。 棧是一種先進后出的數(shù)據(jù)結(jié)構(gòu),棧有一個存儲區(qū)、一個棧頂指針。棧頂指針指向堆棧中第一個可用的數(shù)據(jù)項(被稱為棧頂)。用戶可以在棧頂上方向棧中加入數(shù)據(jù),這個操作被稱為壓棧(Push),壓棧以后,棧頂自動變成新加入數(shù)據(jù)項的位置,棧頂指針也隨之修改。用戶也可以從堆棧中取走棧頂,稱為彈出棧(pop),彈出棧后,棧頂下的一個元素變成棧頂,棧頂指針隨之修改。 函數(shù)調(diào)用時,調(diào)用者依次把參數(shù)壓棧,然后調(diào)用函數(shù),函數(shù)被調(diào)用以后,在堆棧中取得數(shù)據(jù),并進行計算。函數(shù)計算結(jié)束以后,或者調(diào)用者、或者函數(shù)本身修改堆棧,使堆棧恢復(fù)原裝。 在參數(shù)傳遞中,有兩個很重要的問題必須得到明確說明: · 當(dāng)參數(shù)個數(shù)多于一個時,按照什么順序把參數(shù)壓入堆棧 · 函數(shù)調(diào)用后,由誰來把堆棧恢復(fù)原裝 在高級語言中,通過函數(shù)調(diào)用約定來說明這兩個問題。常見的調(diào)用約定有: · stdcall · cdecl · fastcall · thiscall C6中的函數(shù)調(diào)用約定; 調(diào)用約定 堆棧清除 參數(shù)傳遞 __cdecl 調(diào)用者 從右到左,通過堆棧傳遞 __stdcall 函數(shù)體 從右到左,通過堆棧傳遞 __fastcall 函數(shù)體 從右到左,優(yōu)先使用寄存器(ECX,EDX),然后使用堆棧 thiscall 函數(shù)體 this指針默認(rèn)通過ECX傳遞,其它參數(shù)從右到左入棧 __cdecl是C/C++的默認(rèn)調(diào)用約定; VC的調(diào)用約定中并沒有thiscall這個關(guān)鍵字,它是類成員函數(shù)默認(rèn)調(diào)用約定; C/C++中的main(或wmain)函數(shù)的調(diào)用約定必須是__cdecl,不允許更改; 默認(rèn)調(diào)用約定一般能夠通過編譯器設(shè)置進行更改,如果你的代碼依賴于調(diào)用約定,請明確指出需要使用的調(diào)用約定; Delphi6中的函數(shù)調(diào)用約定; 調(diào)用約定 堆棧清除 參數(shù)傳遞 register 函數(shù)體 從左到右,優(yōu)先使用寄存器(EAX,EDX,ECX),然后使用堆棧 pascal 函數(shù)體 從左到右,通過堆棧傳遞 cdecl 調(diào)用者 從右到左,通過堆棧傳遞(與C/C++默認(rèn)調(diào)用約定兼容) stdcall 函數(shù)體 從右到左,通過堆棧傳遞(與VC中的__stdcall兼容) safecall 函數(shù)體 從右到左,通過堆棧傳遞(同stdcall) Delphi中的默認(rèn)調(diào)用約定是register,它也是我認(rèn)為最有效率的一種調(diào)用方式,而cdecl是我認(rèn)為綜合效率最差的一種調(diào)用方式; VC中的__fastcall調(diào)用約定一般比register效率稍差一些; C++Builder6中的函數(shù)調(diào)用約定; 調(diào)用約定 堆棧清除 參數(shù)傳遞 __fastcall 函數(shù)體 從左到右,優(yōu)先使用寄存器(EAX,EDX,ECX),然后使用堆棧 (兼容Delphi的register) (register與__fastcall等同) __pascal 函數(shù)體 從左到右,通過堆棧傳遞 __cdecl 調(diào)用者 從右到左,通過堆棧傳遞(與C/C++默認(rèn)調(diào)用約定兼容) __stdcall 函數(shù)體 從右到左,通過堆棧傳遞(與VC中的__stdcall兼容) __msfastcall 函數(shù)體 從右到左,優(yōu)先使用寄存器(ECX,EDX),然后使用堆棧(兼容VC的__fastcall) 常見的函數(shù)調(diào)用約定中,只有cdecl約定需要調(diào)用者來清除堆棧; C/C++中的函數(shù)支持參數(shù)數(shù)目不定的參數(shù)列表,比如printf函數(shù);由于函數(shù)體不知道調(diào)用者在堆棧中壓入了多少參數(shù), 所以函數(shù)體不能方便的知道應(yīng)該怎樣清除堆棧,那么最好的辦法就是把清除堆棧的責(zé)任交給調(diào)用者; 這應(yīng)該就是cdecl調(diào)用約定存在的原因吧; VB一般使用的是stdcall調(diào)用約定;(ps:有更強的保證嗎) Windows的API中,一般使用的是stdcall約定;(ps: 有更強的保證嗎) 建議在不同語言間的調(diào)用中(如DLL)最好采用stdcall調(diào)用約定,因為它在語言間兼容性支持最好;總結(jié)
- 上一篇: struct的成员对齐
- 下一篇: 用对齐原则求结构体长度