| 概念 | 定義 | 例子 |
| 左值 | 表達式標識一個內存位置(有地址),可出現在賦值號左邊 | 變量 `ch`、`*cp`、`arr[i]` |
| 右值 | 表達式表示一個數值,無固定內存位置,只能出現在賦值號右邊 | 字面量 `'b'`、表達式 `ch2`、`&ch2`、函數返回值 |
| *cp (解引用) | 訪問 cp 指向的內存單元,**本質是左值**(代表那個內存位置) | `*cp = x` 向該位置寫入 x |
逐行語義分析
第 3 行:`*cp = ch2;`
ch2 是右值:字符變量的值 'b'(ASCII 98)。
*cp 是左值:cp 指向的內存地址(即 &ch)。
- 語義:**將字符 'b' 寫入 cp 指向的內存**(即修改 ch 為 'b')。
- 類型匹配:左邊 `char`(目標內存類型),右邊 `char`(源值類型)✅。
第 4 行:`*cp = &ch2;`
&ch2 是右值:ch2 的**地址**(類型 `char *`)。
*cp 是左值:目標內存地址(類型 `char`)。
- 語義嘗試:**將地址值寫入字符內存單元**。
- 類型不匹配:左邊期望 `char`(1 字節),右邊提供 `char *`(4/8 字節指針)❌。
- 編譯器報錯:`assignment to 'char' from 'char *' makes integer from pointer without a cast`。
為什麼書上說「*cp 作為左值代表指向內容的地址」?
這句話**精確描述了左值的本質**:「左值表達式求值結果是一個內存地址」。
*cp 作為左值時,其「值」是 **cp 指向的那個內存單元的地址**(即 &ch)。
- 賦值操作 `<左值> = <右值>` 的機制:**取右值的位模式,寫入左值代表的地址處**。
- 所以 `*cp = ch2` 實際做的是:取 `ch2` 的位模式(字符編碼),寫入 `&ch` 處。
- 同理 `*cp = &ch2` 試圖做:取 `&ch2` 的位模式(指針地址),寫入 `&ch` 處 —— **寬度不匹配,類型不兼容**。
關鍵認知修正
「*cp 無論作為左值還是右值,代表的都是指向的內容」 —— **錯誤**
| 上下文 | 表達式 | 求值結果 | 含義 |
| 左值上下文(賦值目標) | *cp | 內存地址 &ch | 「這裡有個坑,往這裡填數據」 |
| 右值上下文(取值使用) | *cp | 內存中存儲的值 'b' | 「從這個坑裡取出數據」 |
**左值/右值是表達式在上下文中的屬性,不是表達式本身固有的**。同一個 `*cp`,放在 `=` 左邊是左值(地址),放在右邊是右值(內容)。
類比理解
cp 是「某房間的鑰匙」(地址)。
*cp 是「打開門進入房間」(解引用操作)。
- 房間裡放著一個盒子(內存單元),盒子裡裝著字符
'a'。
*cp = ch2:進房間,把盒子裡的東西換成 'b'。
*cp = &ch2:進房間,試圖把「另一個房間的鑰匙」塞進只能裝字符的盒子 —— **塞不進去**(類型/大小不符)。
總結
*cp 作為左值時,**代表 cp 指向的內存地址**(即「目標位置」),不代表內容。
- 賦值右邊必須是**目標類型兼容的值**(此處為 `char`),而非地址(`char *`)。
- 第 3 行通過:字符值 → 字符內存。第 4 行失敗:指針地址 → 字符內存(類型錯誤)。
- 書中「左值代表地址」論述**始終成立**;關鍵在於理解賦值是「將右值位模式寫入左值地址」,類型必須匹配。
掌握「左值=地址、右值=值、賦值=寫入地址、類型必須匹配」這條主線,指針賦值問題自然迎刃而解。
- 上一篇文章: Java Web 專案包命名慣例:studyfront-device-api 含義解析與最佳實踐
- 下一篇文章: Amoeba 代理連接 MySQL:權限授予正確但無法操作的排查與繞過方案
Copyright ©
程式碼之家 All Rights Reserved