C語言指針表達式深度解析:左值、右值與優先級陷阱
指針表達式是 C 語言靈活性與危險性的來源。本文從左值/右值概念切入,系統分析 &ch、cp、&cp、*cp、*cp+1、*(cp+1)、++cp/cp++、*++cp/*cp++ 八類經典表達式的左右值屬性、求值結果與副作用,助你徹底搞懂指針運算本質。
一、左值與右值核心定義
- 左值:可出現在賦值號左側,代表一個可寫入的內存地址空間(如變數、解引用指針)。
- 右值:可出現在賦值號右側,代表一個具體的數值(如字面量、讀取變數/指針的值)。
- 部分表達式既可作左值也可作右值(如
*cp)。
二、場景設定
char ch = 'a'; // 假設地址 0x23,值 'a'
char *cp = &ch; // cp 地址 0x12,值 0x23 (指向 ch)
三、八類表達式完整分析表
| 表達式 | 右值含義 | 左值合法性 | 左值含義 | 備註 |
&ch | ch 的地址 0x23 | ❌ 非法 | — | 地址常量不可寫 |
cp | cp 存儲的值 0x23 | ✅ 合法 | cp 自身的存儲空間 | 指針變數本身 |
&cp | cp 的地址 0x12 | ❌ 非法 | — | 地址常量不可寫 |
*cp | ch 的值 'a' | ✅ 合法 | ch 的存儲空間 | 解引用 = 間接訪問 |
*cp + 1 | 'a' + 1 = 'b' | ❌ 非法 | — | * 優先級高於 +,結果為臨時值 |
*(cp + 1) | ch 下一個字節的值 | ✅ 合法 | ch 下一個字節的空間 | cp+1 為右值指針,解引用後可寫 |
++cp / cp++ | 前綴:cp+1 後的值;後綴:cp 原值 | ❌ 非法 | — | 副作用:cp 本身修改;整體表達式無地址 |
*++cp / *cp++ | 前綴:cp+1 指向的值;後綴:cp 原指向的值 | ✅ 合法 | 對應指向的存儲空間 | 解引用後獲得左值 |
四、運算符優先級與結合性速查
優先級從高到低:
1. () [] -> . // 函數調用、數組下標、結構體成員
2. * & ++ -- ! ~ (type) sizeof // 單目運算符,右結合
3. * / % // 乘除模
4. + - // 加減
5. << >> // 移位
6. < <= > >= // 關係
7. == != // 相等
8. & // 按位與
9. ^ // 按位異或
10. | // 按位或
11. && // 邏輯與
12. || // 邏輯或
13. ?: // 條件,右結合
14. = += -= ... // 賦值,右結合
15. , // 逗號
關鍵點:*(解引用)與 ++/-- 同級,右結合,故 *cp++ 等價 *(cp++),*++cp 等價 *(++cp)。
五、實戰建議
- 讀懂他人代碼:開源項目常見
*p++、*++p 等簡寫,必須能秒懂。
- 慎用複雜表達式:工程代碼優先清晰,拆分為多條語句,避免副作用導致未定義行為。
- 理解本質:指針運算 = 地址運算 + 間接訪問,掌握左值/右值屬性是避坑關鍵。
六、總結
指針表達式看似花哨,實則遵循嚴格的優先級、結合性、左值/右值規則。通過系統整理八類典型表達式,建立「運算符優先級 → 求值順序 → 左右值屬性 → 結果/副作用」的完整思維鏈,才能在閱讀、編寫、調試 C 代碼時遊刃有餘。
- 上一篇文章: 數據結構C語言實現:Kruskal算法求最小生成樹完整代碼與圖解
- 下一篇文章: Objective-C 多線程創建兩大方式:initWithTarget 與 detachNewThreadSelector 完整示例
Copyright ©
程式碼之家 All Rights Reserved