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

C語言運算符、表達式與語句核心筆記:優先級/副作用/順序點/類型轉換

     編輯:關於C語言

C語言運算符、表達式與語句核心筆記:優先級/副作用/順序點/類型轉換

運算符、表達式、語句是C語言程序的三大構建塊。本文梳理核心概念:表達式求值與副作用、順序點語義、語句分類、類型轉換規則、強制轉換用法,助力寫出正確、高效、可維護的C代碼。

核心定義

  • 表達式:運算符與操作數的組合,**每個表達式都有值**(如 a=5 值為5,3+4 值為7)
  • 語句:程序執行的基本單位,以分號 ; 結尾。表達式加分號即成為表達式語句
  • 復合語句:{ ... } 包裹的多條語句,又稱代碼塊

副作用與順序點——C語言語義基石

  • 副作用:對內存/文件/設備的可觀測修改。如 i++ 修改 i,printf 寫標準輸出
  • 順序點:程序執行中「所有之前的副作用已完成、之後的副作用未開始」的時間點
  • 關鍵順序點:
    • 完整表達式結尾(分號處)
    • ||、&&、?:、,(逗號運算符)運算符處
    • 函數調用進入前(實參求值後)
    • 函數返回時
  • 未定義行為來源:同一順序點間對同一對象多次修改,或修改後又讀取(非為了確定新值)。例:i = i++;、a[i] = i++;

運算符優先級與結合性速查(高→低)

優先級運算符結合性說明
1() [] -> .左→右函數調用、下標、成員訪問
2++ -- + - ! ~ (type) * & sizeof右→左後綴/前綴自增減、一元運算、強轉
3* / %左→右乘除模
4+ -左→右加減
5<< >>左→右移位
6< <= > >=左→右關係比較
7== !=左→右相等比較
8&左→右按位與
9^左→右按位異或
10|左→右按位或
11&&左→右邏輯與(短路)
12||左→右邏輯或(短路)
13?:右→左條件運算符
14= += -= *= /= %= &= ^= |= <<= >>=右→左賦值及複合賦值
15,左→右逗號運算符(求值序列)

自增自減運算符陷阱

int i = 5;
int a = ++i;  // 前綴:先增後用,a=6, i=6
int b = i++;  // 後綴:先用後增,b=6, i=7

// 經典未定義行為:
i = i++;          // UB:同一順序點修改i兩次
printf("%d %d", i++, i++); // UB:參數求值順序未規定
a[i] = i++;       // UB:讀取i用於下標、又修改i

類型轉換規則(隱式/常規算術轉換)

  1. 整型提升:char、short(有符號/無符號)→ int(或 unsigned int)
  2. 常規算術轉換:雙操作數統一為「較高」類型
    • 長雙精度 long double
    • 雙精度 double
    • 單精度 float
    • 無符號長長整型 unsigned long long
    • 長長整型 long long
    • 無符號長整型 unsigned long
    • 長整型 long
    • 無符號整型 unsigned int
    • 整型 int(最低)
  3. 賦值轉換:右值轉換為左值類型(可能截斷/擴展/符號改變)
  4. 函數參數傳遞:char/short→int,float→double(舊式聲明/無原型時)

強制類型轉換

(type_name) expression
// 例:
(long) a;           // int → long
(float) (x / y);    // 整除結果轉float(注意:先整除再轉,精度已失)
(float) x / y;      // x轉float,觸發浮點除法(正確)

// 指針轉換需謹慎:
void* p = &i;
int* pi = (int*)p;  // 正確
// 違反嚴格別名規則:
float* pf = (float*)&i; // UB:通過float* 訪問int對象

最佳實踐建議

  1. 表達式簡潔:單表達式運算符不超過3個,複雜邏輯拆分為多語句
  2. 括號明確意圖:即使優先級正確,加括號提高可讀性:(a & b) | c
  3. 避免副作用疊加:i++ 不要出現在同一表達式多處,或與對 i 的其他訪問混用
  4. 有符號/無符號混用警惕:-1 > 0u 為真(-1轉無符號變巨大),啟用編譯器警告 -Wsign-compare
  5. 浮點比較用 epsilon:fabs(a-b) < 1e-9 替代 a==b

總結

掌握運算符優先級、副作用/順序點語義、類型轉換階梯,是從「能寫出代碼」進階到「寫出正確、無UB、可移植代碼」的分水嶺。建議將本文優先級表、轉換階梯、UB模式收藏備查,代碼評審時重點檢查副作用衝突與有符號/無符號混用場景。

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