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

C語言運算符與表達式全面解析:優先級、類型轉換與條件運算

     編輯:關於C

運算符與表達式是C語言程序進行計算與邏輯判斷的基石。本文系統梳理C語言所有運算符分類、優先級結合規則、隱式類型轉換規則及常見陷阱。

運算符分類總覽

類別運算符目數說明
算術+ - * / % ++ --雙目/單目基本數學運算,%僅適用整數
賦值= += -= *= /= %= <<= >>= &= ^= |=雙目簡單與復合賦值,右結合
關系< > <= >= == !=雙目返回int(1/0)
邏輯&& || !雙目/單目短路求值,!優先級最高
位運算& | ^ ~ << >>雙目/單目操作二進制位
指針/成員* & -> .單目/雙目間接訪問、地址、結構成員
條件? :三目唯一三目運算符,右結合
其他sizeof () , [ ]-類型大小、類型轉換、逗號、下標、調用

優先級與結合性(高→低)


1. 後綴:() [] -> . ++ --
2. 單目:++ -- + - ! ~ * & (type) sizeof  ← 右結合
3. 算術:* / %          ← 左結合
4. 算術:+ -            ← 左結合
5. 移位:<< >>          ← 左結合
6. 關系:< <= > >=      ← 左結合
7. 相等:== !=          ← 左結合
8. 位與:&              ← 左結合
9. 位異或:^            ← 左結合
10. 位或:|             ← 左結合
11. 邏輯與:&&          ← 左結合
12. 邏輯或:||          ← 左結合
13. 條件:? :           ← 右結合
14. 賦值:= += -= ...   ← 右結合
15. 逗號:,             ← 左結合

口訣:單目>算術>移位>關系>相等>位&>位^>位|>邏輯&>邏輯|>條件>賦值>逗號

關鍵細節深度解析

自增自減的前後綴差異


int a = 5, b;
b = ++a;  // a=6, b=6  先增後用
b = a++;  // a=6, b=5  先用後增

複雜表達式中混用前後綴屬於未定義行為(C標準未規定求值順序),如a = i++ + ++i,嚴禁編寫。

整數除法與取模

  • 7 / 3 == 2,-7 / 3在C99前實現定義,C99規定向零截斷(結果-2)
  • a % b符號與被除數a相同(C99規定)

隱式類型轉換(整型提升與常用算術轉換)

規則:運算前將操作數轉換為「更高」類型,保證精度不丟失:

  1. 整型提升:char/short/bool/enum → int(或unsigned int)
  2. 常用算術轉換:雙操作數按級別提升
    
      long double > double > float > unsigned long long > long long > 
      unsigned long > long > unsigned int > int
      

陷阱:unsigned int + int → unsigned int,負數變大正數:


int a = -1;
unsigned int b = 1;
printf("%d\n", a + b); // 輸出 0 (無符號運算: UINT_MAX + 1 = 0)

邏輯運算符短路求值


if (p != NULL && p->value > 0)  // p為NULL時不訪問p->value,安全
if (x > 0 || func())            // x>0為真時不調用func()

利用短路特性可簡化條件判斷、避免空指針解引用、優化性能。

條件運算符(三目運算符)


int max = (a > b) ? a : b;
// 等價於
int max;
if (a > b) max = a; else max = b;
  • 結果類型為第二、三操作數的公共類型(經常用算術轉換)
  • 可作為左值(C++):(cond ? a : b) = value;
  • 嵌套可讀性差,建議改用if-else

sizeof運算符

  • 編譯期計算類型/表達式佔用字節數,非函數
  • sizeof(int)需括號,sizeof x變量可不加括號
  • sizeof(arr)得整個數組大小(僅數組定義作用域內),退化為指針時得指針大小
  • sizeof("abc") == 4(含結束符\0)

表達式求值順序陷阱

C標準未規定函數參數、運算符操作數的求值順序(除&&、||、?:、,有序點)。


int i = 5;
printf("%d %d %d\n", i++, i++, i++); // 未定義行為!輸出不可預期
func(i++, i++); // 參數求值順序未定義

鐵律:同一表達式中不得對同一變量既修改又讀取(除非用序列點分隔)。

最佳實踐建議

  • 複雜表達式加括號明確意圖,不依賴優先級記憶
  • 避免在同一語句中多次修改同一變量
  • 有符號與無符號混合運算時顯式轉型
  • 浮點數比較用fabs(a-b) < EPS,避免==
  • 條件運算符僅用於簡單賦值/返回,複雜邏輯用if-else
  • 啟用編譯器警告(-Wall -Wextra -Wsequence-point)捕獲求值順序問題

精通運算符優先級、類型轉換規則與求值順序,是編寫正確、可移植、無未定義行為C代碼的前提。

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