為了這句話丟了很多次人.無所謂了,反正咱臉皮厚.
總結一下: 編譯出來的c/c++程序的參數壓棧順序只和編譯器相關!
下面列舉了一些常見的編譯器的調用約定
VC6:
調用約定 堆棧清除 參數傳遞
__cdecl 調用者 從右到左,通過堆棧傳遞
__stdcall 函數體 從右到左,通過堆棧傳遞
__fastcall 函數體 從右到左,優先使用寄存器(ECX,EDX),然后使用堆棧
thiscall 函數體 this指針默認通過ECX傳遞,其它參數從右到左入棧
__cdecl是C\C++的默認調用約定; VC的調用約定中并沒有thiscall這個關鍵字,它是類成員函數默認調用約定;
C\C++中的main(或wmain)函數的調用約定必須是__cdecl,不允許更改;
默認調用約定一般能夠通過編譯器設置進行更改,如果你的代碼依賴于調用約定,請明確指出需要使用的調用約定;
C++Builder6:
調用約定 堆棧清除 參數傳遞
__fastcall 函數體 從左到右,優先使用寄存器(EAX,EDX,ECX),然后使用堆棧 (兼容Delphi的register)
(register與__fastcall等同)
__pascal 函數體 從左到右,通過堆棧傳遞
__cdecl 調用者 從右到左,通過堆棧傳遞(與C\C++默認調用約定兼容)
__stdcall 函數體 從右到左,通過堆棧傳遞(與VC中的__stdcall兼容)
__msfastcall 函數體 從右到左,優先使用寄存器(ECX,EDX),然后使用堆棧(兼容VC的__fastcall)
上述資料來源于HouSisong的一篇文章:http://www.allaboutprogram.com/index.php?option=content&task=view&id=29&Itemid=31.
由于能力和資源有限,只能找到這些東西,主要的差異體現在fastcall上面,vc是前兩個參數放入寄存器,后面的壓棧,bcb是前3哥參數使用寄存器,
更有變態的,一個朋友朋友說有的參數超過7個以后前5個從左到右傳遞,后面的從右到走,上面說的不可不信,不可全信.
如何確定你的編譯采用的那種順序那?
#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]\n",k,&k);
printf("j=%d:[%x]\n",j,&j);
printf("i=%d:[%x]\n",i,&i);
printf("___________\n");
printf("l:%x\n",&l);
printf("g:%x\n",&g);
}
看看k->i的地址的增長順序和l->g的順序是否相同,如果相同則是從右到左,否則從左到右.
PS:
本來通過打印參數的值來判斷那個先入棧,結果被一個朋友批評了,
他說:壓棧順序和參數計算順序不是一回事,所以還是看地址更有保證.
//看過的朋友當作笑談吧。