stdcall 與 cdecl 的區別

2021-05-17 20:30:19 字數 1867 閱讀 5421

_stdcall 與 _cdecl 的區別

幾乎我們寫的每乙個windows api函式都是__stdcall型別的,首先,需要了解兩者之間的區別: windows的函式呼叫時需要用到棧(stack,一種先入後出的儲存結構)。當函式呼叫完成後,棧需要清除,這裡就是問題的關鍵,如何清除??如果我們的函式使用了_cdecl,那麼棧的清除工作是由呼叫者,用com的術語來講就是客戶來完成的。這樣帶來了乙個棘手的問題,不同的編譯器產生棧的方式不盡相同,那麼呼叫者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的問題就解決了,函式自己解決清除工作。所以,在跨(開發)平台的呼叫中,我們都使用__stdcall(雖然有時是以winapi的樣子出現)。那麼為什麼還需要_cdecl呢?當我們遇到這樣的函式如fprintf()它的引數是可變的,不定長的,被呼叫者事先無法知道引數的長度,事後的清除工作也無法正常的進行,因此,這種情況我們只能使用_cdecl。到這裡我們有乙個結論,如果你的程式中沒有涉及可變引數,最好使用__stdcall關鍵字。

另:_cdecl

按從右至左的順序壓引數入棧,由呼叫者把引數彈出棧。對於「c」函式或者變數,修飾名是在函式名前加下劃線。對於「c++」函式,有所不同。

如函式void test(void)的修飾名是_test;對於不屬於乙個類的「c++」全域性函式,修飾名是?test@@zaxxz

。這是mfc預設呼叫約定。由於是呼叫者負責把引數彈出棧,所以可以給函式定義個數不定的引數,如printf函式。

stdcall 和pascal一樣,都是pascal的呼叫習慣

按從右至左的順序壓引數入棧,由被呼叫者把引數彈出棧。對於「c」函式或者變數,修飾名以下劃線為字首,然後是函式名,然後是符號「@」及引數的位元組數,如函式int func(int a, double b)的修飾名是_func@12

。對於「c++」函式,則有所不同。

_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, ...);

stdcall 與 cdecl 的區別

幾乎我們寫的每乙個windows api函式都是 stdcall型別的,首先,需要了解兩者之間的區別 windows的函式呼叫時需要用到棧 stack,一種先入後出的儲存結構 當函式呼叫完成後,棧需要清除,這裡就是問題的關鍵,如何清除?如果我們的函式使用了 cdecl,那麼棧的清除工作是由呼叫者,用...

stdcall與cdecl的區別

1 區別vc 的c c 函式有兩種基本的呼叫約定 stdcall cdecl stdcall cdecl 函式 cint stdcalladds int a,int b int cdecladdc int a,int b asm32 push ebp mov ebp,esp sub esp,40h ...

stdcall與 cdecl的區別

1 stdcall是pascal程式的預設呼叫方式,通常用於win32 api中,函式採用從右到左的壓棧方式,自己在退出時清空堆疊。vc將函式編譯後會在函式名前面加上下劃線字首,在函式名後加上 和引數的位元組數。int f void p f 4 在外部組合語言裡可以用這個名字引用這個函式 2 c呼叫...