看到有人提問到,在處理printf/cout時,壓棧順序是什么樣的?大家都知道是從右往左,也就是說從右往左的計算,但是,這里的計算不等於輸出。
a++和++a的壓棧的區別:在計算時,遇到a++會記錄此時的a的值作為最后的輸出結果。遇到a和++a的時候則不會將此時的計算結果作為最終的輸出,只會修改a的值,在最終輸出的時候都輸出a的值(所以++a和a的結果總是一樣的)。
比如:
int a = 2; cout << ++a << a++ << a << ++a << a++ << a << ++a << endl;
輸出為:7 5 7 7 3 7 7
但是不禁要問,為什么C語言的函數調用入參壓棧順序一定是自右向左?反過來不可以嗎?
首先,在函數調用過程中,最先入棧的是調用函數調用處的下一條指令的地址,這樣調用完成后返回到該地址繼續執行,這個地址是很重要的,然后才是函數的入參,函數的內部局部變量。調用結束,將棧內容一一出棧,最后棧頂指向了開始存儲的指令地址,主函數繼續從這里開始還行。
其次,函數調用入參的入棧順序和C語言支持變長參數有關,比如printf函數就支持變長參數,也即void printf(const char *fmt,……),這個時候並不知道參數有多少個,如果從左向右入棧,那么fmt就在棧底,該參數的位置無法通過棧頂指針偏移來確定,因為不知道棧頂和棧底之間有多少個參數,大小是多少,無法確定,但是,如果從右向左入棧的話,fmt參數就在棧頂的位置,通過這個固定的普通參數就可以通過偏移逐一尋址到后續參數的地址。
