條件運算式 ? 真值運算式 : 假值運算式
唯一的**三元運算子**,從右向左結合。先求值「條件運算式」(標量型別,非 0 為真),為真則求值並產出「真值運算式」,否則求值並產出「假值運算式」。**只有一個分支會被求值**(短路特性)。
int max = (a > b) ? a : b; // 取較大值
int abs_x = (x >= 0) ? x : -x; // 絕對值
char *msg = (status == 0) ? "OK" : "FAIL"; // 字串字面常數指標
編譯器依照「常見算術轉換」推導兩分支的**共同型別**:
double d = (cond) ? 1 : 2.0; // 結果 double,1 隱含轉 1.0
const char *p = (c) ? "yes" : NULL; // 結果 const char*
條件運算子優先級**僅高於賦值、逗號、throw**,**低於邏輯或 (`||`)、邏輯與 (`&&`)、位元或 (`|`)、比較 (`<`, `==` 等)、算術 (`+`, `*`) 等**。
| 寫法 | 實際解析 | 結果 |
|---|---|---|
a ? b : c = d | a ? b : (c = d) | 賦值在冒號右側 |
a ? b : c + d | a ? b : (c + d) | 加法先於冒號 |
a == b ? c : d | (a == b) ? c : d | 比較先於條件運算子 |
a || b ? c : d | a || (b ? c : d) | ⚠️ 邏輯或優先級更高! |
鐵律:複雜條件或嵌套時,務必加括號明確意圖。
| 誤區 | 正確做法 |
|---|---|
把 `?:` 當成 `if-else` 陳述式用(x > 0) ? foo() : bar(); (合法但不推薦) | 單純為副作用用 `if-else`,`?:` 專用於**產出值** |
嵌套過深導致不可讀a ? b : c ? d : e ? f : g | 提取中間變數、改用 `if-else if-else`、或重構為查表/策略模式 |
副作用順序誤解x = (cond) ? (y++) : (z++); | 只有被選分支的副作用會發生,另一邊**完全不求值** |
型別不相容導致隱含轉換失真(cond) ? 1LL : 1.0 → `double`,大整數可能失精度 | 明確轉型:`(cond) ? (double)1LL : 1.0` 或統一用 `long double` |
struct S s = { .x = (cond) ? 1 : 2, .y = 3 };條件運算子是**表達式級的 if-else**,簡潔有力、支援常數表達式、利於編譯器優化(無分支/向量化)。掌握**型別推導規則、優先級陷阱、短路語意**,善用括號與中間變數,讓它成為你表達「值選擇」利器,而非可讀性殺手。