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

C語言運算符完全手冊:優先級、結合性、副作用與最佳實踐

     編輯:C 語言問答

運算符分類總覽

類別運算符關鍵點
後綴/原子() [] -> . ++ --最高優先級,左結合
一元++ -- + - ! ~ * & sizeof _Alignof右結合,sizeof 不計算表達式值
乘法性* / %左結合,% 僅整數
加法性+ -左結合,指針算術特殊規則
移位<< >>左結合,負數右移實現相關
關系< <= > >=左結合,結果 0/1
相等== !=左結合,**別寫成 =**
位與&左結合
位異或^左結合
位或|左結合
邏輯與&&左結合,**短路求值**
邏輯或||左結合,**短路求值**
條件?:**唯一三目**,右結合
賦值= += -= *= /= %= <<= >>= &= ^= |=右結合,**返回左值**
逗號,最低優先級,左結合,**序列點**

核心陷阱與最佳實踐

1. = vs == (經典 Bug)


if (a = 5)  // ❌ 賦值,結果 5 (真),永遠執行
if (a == 5) // ✅ 比較
// 防禦寫法:常量左側
if (5 == a) // 誤寫成 5 = a 會編譯錯誤

2. 短路求值副作用


int x = 0;
if (x || func())  // x 為 0,func() 會被調用
if (x && func())  // x 為 0,func() **不會**調用
// 依賴副作用的邏輯極易出錯,避免在 &&/|| 中放函數調用/賦值

3. 自增自減副作用與序列點


int i = 1;
int a = i++ + ++i; // ❌ 未定義行為:同一表達式多次修改 i 且無序列點
// 正確:拆分語句
int t1 = i++;
int t2 = ++i;
int a = t1 + t2;

4. 條件運算符結合性


a = b ? c : d ? e : f; // 解析為 a = b ? c : (d ? e : f) (右結合)
// 建議加括號明確意圖
a = b ? c : (d ? e : f);

5. 逗號運算符 vs 函數參數分隔


int a = (1, 2, 3);     // a = 3,逗號運算符,返回最後表達式值
func(1, 2, 3);         // 三個參數,非逗號運算符,無序列點保證求值順序
// C17 規定函數參數求值順序未指定,不要依賴順序

6. sizeof 不計算表達式


int i = 0;
size_t s = sizeof(i++); // s = sizeof(int),i **不會** 增加
// sizeof 類型/表達式均在編譯期確定大小,不產生代碼

優先級速查口訣(由高到低)


后缀 () [] -> .
一元 ++ -- + - ! ~ * & sizeof
乘除模 * / %
加减 + -
移位 << >>
关系 < <= > >=
相等 == !=
位与 &
位异或 ^
位或 |
逻辑与 &&
逻辑或 ||
条件 ?:
赋值 = += -= ...
逗号 ,

總結

  • **優先級決定「誰先綁定誰」**,**結合性決定「同級誰先算」**。
  • **短路求值 (&&/||/?:) 是語義保證,不是優先級**,利用它寫安全檢查:p && p->next。
  • **副作用 (賦值/自增/函數調用) 與複雜表達式混用 = UB 溫床**,拆分語句、用中間變量。
  • **不確定時加括號**:寫 (a + b) * c 而非依賴記憶,代碼給人看,順便給編譯器看。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved