運行以下代碼:
void print(int x,int y,int z){ cout<<"&x= "<<&x<<endl; cout<<"&y= "<<&y<<endl; cout<<"&z= "<<&z<<endl; } int main() { print(1,1,1); getchar(); }
輸出:
首先明確一個事實:在一個進程的內存圖中,棧段位於上部,並且從高地址到低地址擴展,不會的可以看這里:https://www.cnblogs.com/FdWzy/p/12424308.html
從圖中我們發現x,y,z的地址逐漸變大,表明:函數參數入棧順序是從右到左的。(自己畫一下圖很好理解)
原因:由於c語言有不定長參數函數,比如下面這個:
int add(int num,...) { va_list valist; //用於放參數 int sum = 0; int i; /* 以num個參數初始化valist */ va_start(valist, num); /* 把參數放進valist */ for (i = 0; i < num; i++) { sum += va_arg(valist, int); } /* 清理內存 */ va_end(valist); return sum; } int main() { cout<<add(3,1,5,7);//res=13 getchar(); }
其運行原理是:num指示參數個數,然后函數體內部的valist是一個void*指針,每次移sizeof(int)大小,即每次取1個int參數。但我也沒有研究過這個方面,大概知道有這么個東西就行
總之我想說的是,如果函數調用是從左到右入棧參數,像上面的函數參數形成的棧就是這樣的:num,1,2,3。
其中num在棧底,3在棧頂。但是由於這是個不定參數函數,需要這個num的值去確定我們參數的個數,但num在棧底我們抽不出來阿,問題就在這兒。
如果從右到左入棧的話就不存在這個問題了。
參考: