生活随笔
收集整理的這篇文章主要介紹了
函数调用约定
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
函數(shù)調(diào)用約定
標(biāo)簽:? 函數(shù)? 調(diào)用? 約定?
2008-11-14 15:40
計(jì)算機(jī)提供了一種被稱為棧的數(shù)據(jù)結(jié)構(gòu)來支持參數(shù)傳遞。
棧是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu),棧有一個(gè)存儲(chǔ)區(qū)、一個(gè)棧頂指針。棧頂指針指向堆棧中第一個(gè)可用的數(shù)據(jù)項(xiàng)(被稱為棧頂)。用戶可以在棧頂上方向棧中加入數(shù)據(jù),這個(gè)操作被稱為壓棧(Push),壓棧以后,棧頂自動(dòng)變成新加入數(shù)據(jù)項(xiàng)的位置,棧頂指針也隨之修改。用戶也可以從堆棧中取走棧頂,稱為彈出棧(pop),彈出棧后,棧頂下的一個(gè)元素變成棧頂,棧頂指針隨之修改。
函數(shù)調(diào)用時(shí),調(diào)用者依次把參數(shù)壓棧,然后調(diào)用函數(shù),函數(shù)被調(diào)用以后,在堆棧中取得數(shù)據(jù),并進(jìn)行計(jì)算。函數(shù)計(jì)算結(jié)束以后,或者調(diào)用者、或者函數(shù)本身修改堆棧,使堆?;謴?fù)原裝。
在參數(shù)傳遞中,有兩個(gè)很重要的問題必須得到明確說明:
· 當(dāng)參數(shù)個(gè)數(shù)多于一個(gè)時(shí),按照什么順序把參數(shù)壓入堆棧
· 函數(shù)調(diào)用后,由誰來把堆?;謴?fù)原裝
在高級(jí)語言中,通過函數(shù)調(diào)用約定來說明這兩個(gè)問題。常見的調(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這個(gè)關(guān)鍵字,它是類成員函數(shù)默認(rèn)調(diào)用約定;
C/C++中的main(或wmain)函數(shù)的調(diào)用約定必須是__cdecl,不允許更改;
默認(rèn)調(diào)用約定一般能夠通過編譯器設(shè)置進(jìn)行更改,如果你的代碼依賴于調(diào)用約定,請(qǐng)明確指出需要使用的調(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:有更強(qiáng)的保證嗎)
Windows的API中,一般使用的是stdcall約定;(ps: 有更強(qiáng)的保證嗎)
建議在不同語言間的調(diào)用中(如DLL)最好采用stdcall調(diào)用約定,因?yàn)樗谡Z言間兼容性支持最好;
總結(jié)
以上是生活随笔為你收集整理的函数调用约定的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。