#include
#include
using namespace std;
int main() {
int a = 15;
printf("%d,%d,%d", ++a, a++, 10 * a++);
return 0;
}
輸出結果:18, 17, 150
C 標準(C99/C11/C18)明確指出:函數參數的求值順序未指定,且同一序列點內對同一變量的多次修改、或修改後又讀取,屬於未定義行為(Undefined Behavior, UB)。
++a(前置遞增)、a++(後置遞增)多次修改 a。10 * a++ 中既讀取 a 又修改 a。某編譯器(如 MSVC)恰好採用「從右向左」壓棧求值,且後置遞增語義為「先取值後遞增」,前置遞增為「先遞增後取值」,才產生 18, 17, 150。但:
-O0 vs -O2)結果可能不同。int a = 15;
int p1 = ++a; // a=16, p1=16
int p2 = a++; // p2=16, a=17
int p3 = 10 * a++; // p3=170, a=18
printf("%d,%d,%d", p1, p2, p3); // 16,16,170 確定性輸出
-Wall -Wextra -Wsequence-point 或 /Wall)可捕獲大多數此類問題。C++17 對運算子優先級與求值順序有細微調整(如 a << b << c 左運算元優先求值),但函數參數求值順序仍未規定。現代 C++ 推薦使用 std::format(C++20)或 iostream 避免此類陷阱。