在實驗中觀察指針——C++ 函數參數的壓棧順序


前言

好久沒寫東西了,突發奇想,寫寫函數參數的壓棧順序
先看看這個問題
https://q.cnblogs.com/q/137133/

然后看我簡化的代碼,猜輸出結果是多少?

#include<bits/stdc++.h>
using namespace std;
int main(){
    int i=0;
    printf("%d %d",i++,i--);
    return 0;
}

根據++和--的特性,i++的時候數值不變,輸出0,i--時i才加上1,輸出1。
事實是這樣嗎?我在多台編譯器上執行,輸出的結果都是:

-1 0

根據我之前寫過的指針篇的內容,函數的局部變量保存在棧中,都是獨立的,參數同樣保存在棧中,才導致了swap函數改變函數參數必須使用指針。
那么,函數參數,在棧中是如何排列的呢?順序?倒序?
我們寫一個簡短的代碼,來實驗一下。

#include<bits/stdc++.h>
using namespace std;
void test(int a,int b){
    printf("a..%p, b..%p",&a,&b);
}
int main(){
    int a,b;
    test(a,b);
}

由於是地址,不同編譯器的結果不同。但肯定的是,a比b大4。
如果多加幾個變量進去,我們發現,地址的大小從大到小遞減。

棧模型

圖源:《征服C指針》

從這張圖中可以看出,C語言中,參數是從后往前堆積在棧中的。這種處理方式的好處在於,無論有多少個參數,總能找到第一個參數的地址,這樣就可以順次找到后面的參數。否則,從后往前,就無法找到第一個參數,也無法實現可變長參數的功能。
例如在printf中,我們找到第一個參數的位置,例如"%d %s",就可以順次解析后面的地址的參數,因為參數是連續在內存排列的。

問題解釋

既然參數是從后往前放入棧中的,那么,我們就可以解釋這個問題了。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int i=0;
    printf("%d %d",i++,i--);
    return 0;
}

開頭的代碼。如果編譯成匯編語言進行執行,應該是這個樣子(如果有錯誤請指正,手寫的)

sub [i],1 ;i--
push [i]
add [i],1 ;i++
push [i]
push offset string "%d %d" ;"%d %d"
call dword ptr_printf ;調用printf

在匯編語言中,push是將參數壓入棧的一個指令,由於這篇文章不是講匯編的,大家看看就好。
因此,在推入棧的時候,先執行了i--,再執行i++,結果也當然是這樣了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM