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

C 語言未定義行為經典案例:同一表達式多次修改 i++ 導致結果不可預期

     編輯:關於C語言

C 語言未定義行為經典案例:同一表達式多次修改 i++ 導致結果不可預期

問題代碼

int i = 0;
int a[] = {10, 20, 30};
int r = 1 * a[i++] + 2 * a[i++] + 3 * a[i++];
printf("%d\n", r); // GCC 4.7.3 輸出 60

為什麼是未定義行為 (UB)

C 標準 (C11 6.5/2) 規定:若同一表達式中對同一標量物件進行多次修改,或修改後又讀取其值 (非為了決定新值),行為未定義。

此處 i 在同一表達式中被修改三次 (i++),且其值被用於陣列索引,屬於多次修改且讀取值不為決定新值 → UB。

編譯器實際行為 (GCC x86_64 -O0)

反組譯顯示:三次 a[i++] 皆在 i 遞增前使用 i=0,即皆取 a[0]=10。
計算:1*10 + 2*10 + 3*10 = 60。
三次遞增指令集中在表達式計算完成後執行。

序列點與副作用

  • 副作用:修改物件值 (如 i++ 的遞增)。
  • 序列點:副作用確定完成、下一步驟尚未開始的時間點 (如語句結尾 ;、函數呼叫前後、&&/||/?:/, 運算子)。
  • 標準僅保證副作用在下一序列點前完成,不保證相對順序。

正確寫法

int i = 0;
int r = 1 * a[i] + 2 * a[i+1] + 3 * a[i+2];
i += 3; // 明確分離修改與讀取

教訓

  1. 避免在單一表達式中多次修改同一變數。
  2. 啟用編譯器警告:-Wall -Wextra -Wsequence-point (GCC/Clang)。
  3. 使用靜態分析工具 (Cppcheck, Clang Static Analyzer) 檢測 UB。

理解 UB 是寫出健壯 C 程式的關鍵,切勿依賴特定編譯器行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved