語法與語義
condition ? expr_true : expr_false
// 等價於
if (condition) result = expr_true; else result = expr_false;
// 但它是**表達式**,有值,可嵌套、可作函數參數、可賦值給變量
核心規則
- 求值順序固定:先求
condition,為真 (非 0) 求 expr_true,為假 (0) 求 expr_false。**短路求值**,未選分支**絕不求值** (無副作用);
- 結果類型:按「常規算術轉換」統一
expr_true 和 expr_false 類型 — 整數提升 → 整數轉換 → 浮點轉換。
例:int a=1; double b=2.0; (cond?a:b) 類型為 double;
- 左值屬性:若兩分支均為左值且類型兼容,結果為左值,可賦值:
(cond ? a : b) = 10;;
- 優先級:低於賦值、逗號,高於邏輯或。
a = b ? c : d 等價 a = (b ? c : d);
- 結合性:右結合。
a ? b : c ? d : e 解析為 a ? b : (c ? d : e)。
實用模式
1. 邊界夾持
val = (val < MIN) ? MIN : (val > MAX) ? MAX : val;
2. 安全指針解引用
int val = ptr ? *ptr : DEFAULT;
3. 避免除零
double ratio = denom != 0 ? num / denom : 0.0;
4. 編譯期常量 (C99 指定初始化器配合)
#define MAX(a,b) ((a) > (b) ? (a) : (b)) // 參數加括號防運算符優先級錯誤
// 但宏有副作用風險,C23 引入 constexpr 函數更安全
避坑指南
- ❌
a ? b : c = d 解析為 a ? b : (c = d) — 加括號 (a ? b : c) = d (需左右皆左值);
- ❌ 嵌套超過 2 層 — 可讀性崩潰,改用
if-else 鏈;
- ❌ 分支有副作用且依賴順序 —
cond ? func1() : func2() 只有選中分支執行,但閱讀者易誤解;
- ✅ 簡單、無副作用、類型明確的選擇場景首選三元運算符;
- ✅ 複雜邏輯用
if-else,編譯器優化效果相同。