整理日:2015年3月18日c++
爲了這句話丟了不少次人.無所謂了,反正咱臉皮厚.函數
總結一下ui
編譯出來的c/c++程序的參數壓棧順序只和編譯器相關!this
下面列舉了一些常見的編譯器的調用約定指針
VC6code
調用約定 | 堆棧清除 | 參數傳遞 |
---|---|---|
__cdecl | 調用者 | 從右到左,經過堆棧傳遞 |
__stdcall | 函數體 | 從右到左,經過堆棧傳遞 |
__fastcall | 函數體 | 從右到左,優先使用寄存器(ECX,EDX),而後使用堆棧 |
thiscall | 函數體 | this指針默認經過ECX傳遞,其它參數從右到左入棧 |
__cdecl是CC++的默認調用約定; VC的調用約定中並無thiscall這個關鍵字,它是類成員函數默認調用約定;
CC++中的main(或wmain)函數的調用約定必須是__cdecl,不容許更改;
默認調用約定通常可以經過編譯器設置進行更改,若是你的代碼依賴於調用約定,請明確指出須要使用的調用約定;資源
C++Builder6編譯器
調用約定 | 堆棧清除 | 參數傳遞 |
---|---|---|
__cdecl | 調用者 | 從右到左,經過堆棧傳遞(與CC++默認調用約定兼容) |
__stdcall | 函數體 | 從右到左,經過堆棧傳遞(與VC中的__stdcall兼容) |
__fastcall | 函數體 | 從左到右,優先使用寄存器(EAX,EDX,ECX),而後使用堆棧 (兼容Delphi的register) |
msfastcall | 函數體 | 從右到左,優先使用寄存器(ECX,EDX),而後使用堆棧(兼容VC的__fastcall) |
__pascal | 函數體 | 從左到右,經過堆棧傳遞 |
因爲能力和資源有限,只能找到這些東西,主要的差別體如今fastcall上面,vc是前兩個參數放入寄存器,後面的壓棧,bcb是前3哥參數使用寄存器, 更有變態的,一個朋友朋友說有的參數超過7個之後前5個從左到右傳遞,後面的從右到走,上面說的不可不信,不可全信.源碼
如何肯定你的編譯採用的那種順序那?it
#include <stdio.h> int f(int i,int j,int k); int main() { static int i=0; f(i++,i++,i++); return 0; } int f(int i,int j,int k) { int l; int g; printf("k=%d:[%x] ",k,&k); printf("j=%d:[%x] ",j,&j); printf("i=%d:[%x] ",i,&i); printf("\_\_\_\_\_\_\_\_\_\__ "); printf("l:%x ",&l); printf("g:%x ",&g); }
看看k->i的地址的增加順序和l->g的順序是否相同,若是相同則是從右到左,不然從左到右.
PS
原本經過打印參數的值來判斷那個先入棧,結果被一個朋友批評了,
他說:壓棧順序和參數計算順序不是一回事,因此仍是看地址更有保證.
看過的朋友看成笑談吧。
曾經看到一篇文章上面說:c/c++參數壓棧順序是從右到左,pascal參數壓棧是從左到右.
注意點