_cdecl 是c declaration的縮寫,表示c語言預設的函式呼叫方法:所有引數從右到左依次入棧,這些引數由呼叫者清除,稱為手動清棧。被呼叫函式無需要求呼叫者傳遞多少引數,呼叫者傳遞過多或者過少的引數,甚至完全不同的引數都不會產生編譯階段的錯誤。
_stdcall 是standard call的縮寫,是c++的標準呼叫方式:所有引數從右到左依次入棧,如果是呼叫類成員的話,最後乙個入棧的是this指標。這些堆疊中的引數由被呼叫的函式在返回後清除,使用的指令是 retn x,x表示引數占用的位元組數,cpu在ret之後自動彈出x個位元組的堆疊空間。稱為自動清棧。函式在編譯的時候就必須確定引數個數,並且呼叫者必須嚴格的控制引數的生成,不能多,不能少,否則返回後會出錯。
pascal 是pascal語言的函式呼叫方式,也可以在c/c++中使用,引數壓棧順序與前兩者相反。返回時的清棧方式忘記了。。。
_fastcall 是編譯器指定的快速呼叫方式。由於大多數的函式引數個數很少,使用堆疊傳遞比較費時。因此_fastcall通常規定將前兩個(或若干個)引數由暫存器傳遞,其餘引數還是通過堆疊傳遞。不同編譯器編譯的程式規定的暫存器不同。返回方式和_stdcall相當。
_thiscall 是為了解決類成員呼叫中this指標傳遞而規定的。_thiscall要求把this指標放在特定暫存器中,該暫存器由編譯器決定。vc使用ecx,borland的c++編譯器使用eax。返回方式和_stdcall相當。
_fastcall 和 _thiscall涉及的暫存器由編譯器決定,因此不能用作跨編譯器的介面。所以windows上的com物件介面都定義為_stdcall呼叫方式。
c中不加說明預設函式為_cdecl方式(c中也只能用這種方式),c++也一樣,但是預設的呼叫方式可以在ide環境中設定。
帶有可變引數的函式必須且只能使用_cdecl方式,例如下面的函式:
int printf(char * fmtstr, ...);
int scanf(char * fmtstr, ...);
這兩個關鍵字看起來似乎很少和我們打交道,但是看了下面的定義(來自windef.h
),你一定會覺得驚訝:
#define callback __stdcall
#define winapi __stdcall
#define winapiv __cdecl
#define apientry winapi
#define apiprivate __stdcall
#define pascal __stdcall
#define cdecl _cdecl
#ifndef cdecl
#define cdecl _cdecl
#endif
幾乎我們寫的每乙個windows api函式都是__stdcall型別的,為什麼??
首先,我們談一下兩者之間的區別:
windows的函式呼叫時需要用到棧(stack,一種先入後出的儲存結構)。當函式
呼叫完成後,棧需要清除,這裡就是問題的關鍵,如何清除??
如果我們的函式使用了_cdecl,那麼棧的清除工作是由呼叫者,用com的術語來講
就是客戶來完成的。這樣帶來了乙個棘手的問題,不同的編譯器產生棧的方式不盡相同
,那麼呼叫者能否正常的完成清除工作呢?答案是不能。
如果使用__stdcall,上面的問題就解決了,函式自己解決清除工作。所以,在跨
(開發)平台的呼叫中,我們都使用__stdcall(雖然有時是以winapi的樣子出現)。
那麼為什麼還需要_cdecl呢?當我們遇到這樣的函式如fprintf()它的引數是可變
的,不定長的,被呼叫者事先無法知道引數的長度,事後的清除工作也無法正常的進行
,因此,這種情況我們只能使用_cdecl。
到這裡我們有乙個結論,如果你的程式中沒有涉及可變引數,最好使用__stdcal
l關鍵字
函式呼叫方式
cdecl 是c declaration的縮寫,表示c語言預設的函式呼叫方法 所有引數從右到左依次入棧,這些引數由呼叫者清除,稱為手動清棧。被呼叫函式不需要求呼叫者傳遞多少引數,呼叫者傳遞過多或者過少的引數,甚至完全不同的引數都不會產生編譯階段的錯誤。stdcall 是standard call的縮...
函式呼叫方式
現代的程式語言的函式竟然有那麼多的呼叫方式。這些東西要完全理解還得通過彙編 才好理解。他們各自有自己的特點 其實這些呼叫方式的差別在主要在一下幾個方面 1.引數處理方式 傳遞順序,訪問 利用盞還是暫存器 2.函式的結尾處理方式 善後處理 如 棧的恢復由誰恢復?函式內恢復 還是呼叫後恢復 以下是理論 ...
函式呼叫方式
所謂的呼叫方式是指 在呼叫乙個函式時,約定的傳遞引數方式和平衡堆疊方式,例如 有乙個函式,它有兩個引數 xyz first,second 當我們使用stdcall呼叫方式時,也就是windows呼叫api的常見方式 又幾個函式例外 它的呼叫方式如下 x1 push second x2 push fi...