首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

後置遞增與前置遞增在表達式中的求值差異:(i++)+(i++) vs (++i)+(++i)

     編輯:關於C++

測試代碼

int main() {
    int i = 3;
    int j = (i++) + (i++);
    // int j = (++i) + (++i);
    printf("%d,%d\n", i, j);
}

VC6.0 結果與彙編分析

(i++) + (i++)

結果:i=5, j=6

mov eax, [ebp-4]   ; i → eax (3)
add eax, [ebp-4]   ; eax = i+i = 6
mov [ebp-8], eax   ; j = 6
mov ecx, [ebp-4]   ; i → ecx (3)
add ecx, 1         ; ecx = 4
mov [ebp-4], ecx   ; i = 4
mov edx, [ebp-4]   ; i → edx (4)
add edx, 1         ; edx = 5
mov [ebp-4], edx   ; i = 5

關鍵點:先用原值 i 計算加法(3+3=6),再做兩次後置遞增。

(++i) + (++i)

結果:i=5, j=10

mov eax, [ebp-4]   ; i → eax (3)
add eax, 1         ; eax = 4
mov [ebp-4], eax   ; i = 4
mov ecx, [ebp-4]   ; i → ecx (4)
add ecx, 1         ; ecx = 5
mov [ebp-4], ecx   ; i = 5
mov edx, [ebp-4]   ; i → edx (5)
add edx, [ebp-4]   ; edx = 10 (i+i)
mov [ebp-8], edx   ; j = 10

關鍵點:先做兩次前置遞增(i 變 5),再用新值計算加法(5+5=10)。

GCC 3.2.2 結果

與 VC6.0 完全一致:(i++)+(i++) → i=5,j=6;(++i)+(++i) → i=5,j=10。GCC 產生的彙編更精簡高效。

Java 行為差異


public class TestAdd {
    public static void main(String[] args) {
        int i = 3;
        int j = (i++) + (i++);  // 5, 7
        // int j = (++i) + (++i); // 5, 9
        System.out.println(i + "," + j);
    }
}

Java 字節碼分析

(++i)+(++i) → i=5, j=9


iconst_3        ; 3 入棧
istore_1        ; i=3
iinc 1, 1       ; i=4
iload_1         ; 壓入 4
iinc 1, 1       ; i=5
iload_1         ; 壓入 5
iadd            ; 彈出 4,5 → 9 入棧
istore_2        ; j=9

(i++)+(i++) → i=5, j=7


iconst_3        ; 3 入棧
istore_1        ; i=3
iload_1         ; 壓入 3
iinc 1, 1       ; i=4
iload_1         ; 壓入 4
iinc 1, 1       ; i=5 (注意:5 未入棧)
iadd            ; 彈出 3,4 → 7 入棧
istore_2        ; j=7

根本原因:棧式 vs 寄存器式架構

特性x86 本地代碼 (VC/GCC)JVM 字節碼
架構寄存器式棧式
運算方式將操作數移至寄存器再運算從棧彈出操作數運算後壓回
副作用可見性內存/寄存器即時更新棧中保存的是「讀取時的值」,後續遞增不影響棧中舊值

C/C++ 標準規定:同一序列點修改同一對象多次,行為未定義。上述結果僅反映特定編譯器/JVM 的實現細節,**不可依賴**。

最佳實踐

  • 避免在單一表達式中對同一變量多次副作用操作
  • 拆分為多條語句:int a = i++; int b = i++; j = a + b;
  • 啟用編譯器警告(/Wall、-Wsequence-point)捕獲此類代碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved