printf壓棧順序之 i++ 及 ++i


i++ 與 ++i 的不同

1 i=1;   printf("%d %d\n",i,i++);         //結果 2 1 2 i=1;   printf("%d %d\n",i++,i);        //結果 1 2 3 i=1;   printf("%d %d %d\n",i,i++,i);      //結果 2 1 2 4 i=1;   printf("%d %d %d %d\n",i,++i,i++,i);  //結果 3 3 1 3

解析:

已知前提:

  1. printf輸出時,壓棧順序為從右往左,也就是說從右往左的計算;
  2. 入棧時先進后出,先進入的在棧的高地址,后進入的在棧的低地址;
  3. printf后面的表達式,比如i++, 此操作為計算,”計算“ 是計算,但是不等於“輸出”的結果;
  4. i++的結果,是有ebp尋址函數棧空間來記錄中間結果的,在最后給printf壓棧的時候,再從ebp棧中把中間結果取出來壓入printf分配的棧中;
  5. ++i的結果,是直接寄存器進行自增操作,然后把該寄存器的地址壓入printf分配的棧中。

 

i++是先計算后自加,而++i是先自加后計算。

1 int  main()
2 {
3     int i = 0;
4     //i++ = 100;//直接報錯,編譯出錯: error C2106: “=”: 左操作數必須為左值
5     ++i=100;//通過,沒有錯誤
6     printf("%d", i);//直接打印100
7     return 0;
8 }

  從上面的代碼情況可以認為編譯器在處理i++和++i的方式不同

  1. i++完成之后返回的是右值也就是一個常量
  2. ++i完成之后返回的是左值也就是i的內存,對++i賦值相當於給i賦值

  結論:printf壓棧的時候,i++其實壓的是ebr中間結果的值,也就是一個常量。而++i 因為計算后的結果是一個左值,故會將i對應的地址進行壓棧。

 

例題說明

i=1;   printf("%d %d %d %d\n",i,++i,i++,i);  //結果 3 3 1 3

++i 是直接真值進行自加,而 i++ 則是通過在ebr中存放的臨時副本進行加1后再賦值給i

運算式 真值(寄存器中) 副本(ebr中)
低位 i 3  
  ++i 3  
  i++ 2 1
高位 i 1  

最終 i 的真值為3,i++ 的ebr定值為1, 故最后的輸出結果為:3 3 1 3

參考:鏈接1鏈接2鏈接3

 


免責聲明!

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



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