C/C++函數挪用的幾種方法總結。本站提示廣大學習愛好者:(C/C++函數挪用的幾種方法總結)文章只能為提供參考,不一定能成為您想要的結果。以下是C/C++函數挪用的幾種方法總結正文
挪用函數時,盤算機經常使用棧來存儲傳遞給函數的參數。
棧是一種先輩後出的數據構造,棧有一個存儲區、一個棧頂指針。棧頂指針指向客棧中第一個可用的數據項(被稱為棧頂)。用戶可以在棧頂上偏向棧中參加數據,這個操作被稱為壓棧(Push),壓棧今後,棧頂主動釀成新參加數據項的地位,棧頂指針也隨之修正。用戶也能夠從客棧中取走棧頂,稱為彈出棧(pop),彈出棧後,棧頂下的一個元素釀成棧頂,棧頂指針隨之修正。函數挪用時,挪用者順次把參數壓棧,然後挪用函數,函數被挪用今後,在客棧中獲得數據,並停止盤算。函數盤算停止今後,或許挪用者、或許函數自己修正客棧,使客棧恢回復復興裝。
在參數傳遞中,有兩個主要的成績必需要明白解釋:
1. 當參數個數多於一個時,依照甚麼次序把參數壓入客棧;
2. 函數挪用後,由誰來把客棧恢回復復興狀。
在高等說話中,就是經由過程函數的挪用方法來講明這兩個成績的。罕見的挪用方法有:
stdcall
cdecl
fastcall
thiscall
thiscall
naked call
上面就分離引見這幾種挪用方法:
1. stdcall
stdcall挪用方法又被稱為Pascal挪用方法。在Microsoft C++系列的C/C++編譯器中,應用PASCAL宏,WINAPI宏和CALLBACK宏來指定函數的挪用方法為stdcall。
stdcall挪用方法的函數聲明為:
int _stdcall function(int a, int b);
stdcall的挪用方法意味著:
(1) 參數從右向左一次壓入客棧
(2) 由被挪用函數本身來恢復客棧
(3) 函數名主動加前導下劃線,前面緊隨著一個@,厥後緊隨著參數的尺寸
下面誰人函數翻譯成匯編說話將釀成:
push b 先壓入第二個參數
push a 再壓入第一個參數
call function 挪用函數
在編譯時,此函數的名字被翻譯為_function@8
2. cdecl
cdecl挪用方法又稱為C挪用方法,是C說話缺省的挪用方法,它的語法為:
int function(int a, int b) // 不加潤飾符就是C挪用方法
int _cdecl function(int a, int b) // 明白指定用C挪用方法
cdecl的挪用方法決議了:
(1) 參數從右向左順次壓入客棧
(2) 由挪用者恢復客棧
(3) 函數名主動加前導下劃線
因為是由挪用者來恢復客棧,是以C挪用方法許可函數的參數個數是不固定的,這是C說話的一年夜特點。
此方法的函數被翻譯為:
push b // 先壓入第二個參數
push a // 在壓入第一個參數
call funtion // 挪用函數
add esp, 8 // 清算客棧
在編譯時,此方法的函數被翻譯成:_function
3. fastcall
fastcall 依照名字上懂得便可以曉得,它是一種疾速挪用方法。此方法的函數的第一個和第二個DWORD參數經由過程ecx和edx傳遞,
前面的參數從右向左的次序壓入棧。
被挪用函數清算客棧。
函數名修個規矩同stdcall
其聲明語法為:
int fastcall function(int a, int b);
4. thiscall
thiscall 挪用方法是獨一一種不克不及顯示指定的潤飾符。它是c++類成員函數缺省的挪用方法。因為成員函數挪用還有一個this指針,是以必需用這類特別的挪用方法。
thiscall挪用方法意味著:
參數從右向左壓入棧。
假如參數個數肯定,this指針經由過程ecx傳遞給被挪用者;假如參數個數不肯定,this指針在一切參數壓入棧後被壓入棧。
參數個數不定的,由挪用者清算客棧,不然由函數本身清算客棧。
可以看到,關於參數個數固定的情形,它相似於stdcall,不准時則相似於cdecl。
5. naked call
是一種比擬少見的挪用方法,普通高等法式設計說話中不罕見。
函數的聲明挪用方法和現實挪用方法必需分歧,必定編譯器會發生凌亂。
函數名字修正規矩:
1. C編譯時函數名潤飾商定規矩:
__stdcall挪用商定在輸入函數名前加上一個下劃線前綴,前面加上一個“@”符號和其參數的字節數,格局為_function@8。
__cdecl挪用商定僅在輸入函數名前加上一個下劃線前綴,格局為_function。
__fastcall挪用商定在輸入函數名前加上一個“@”符號,前面也是一個“@”符號和其參數的字節數,格局為@function@8。
它們均不轉變輸入函數名中的字符年夜小寫,這和PASCAL挪用商定分歧,PASCAL商定輸入的函數名無任何潤飾且全體年夜寫。
2. C++編譯時函數名潤飾商定規矩:
__stdcall挪用商定:
(1)以“?”標識函數名的開端,後跟函數名;
(2)函數名前面以“@@YG”標識參數表的開端,後跟參數表;
(3)參數表以代號表現:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
....
PA--表現指針,前面的代號注解指針類型,假如雷同類型的指針持續湧現,以“0”取代,一個“0”代
表一次反復;
(4)參數表的第一項為該函數的前往值類型,厥後順次為參數的數據類型,指針標識在其所指數據類型前;
(5)參數表後以“@Z”標識全部名字的停止,假如該函數無參數,則以“Z”標識停止。
其格局為“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z”
void Test2() -----“?Test2@@YGXXZ”
__cdecl挪用商定:
規矩同下面的_stdcall挪用商定,只是參數表的開端標識由下面的“@@YG”變成“@@YA”。
__fastcall挪用商定:
規矩同下面的_stdcall挪用商定,只是參數表的開端標識由下面的“@@YG”變成“@@YI”。
VC++對函數的省缺聲明是"__cedcl",將只能被C/C++挪用。