20.左值-vs-右值.md 3.7 KB

左值 vs 右值

判别规则(核心,唯一要记的)

  • 能对它成功取地址 &左值;能放赋值号左边 → 左值;两者都不行 → 右值
  • 两个特殊:数组名是左值但不可赋值(常量地址);const 变量是只读左值(可 & 不可写)——左值 ≠ 可赋值

一句话:"左值住得久有门牌号(地址),右值是过客没门牌。"

抽象描述(一句话本质)

左值 = 有内存地址、可寻址、能放赋值号左边的表达式;右值 = 临时值/纯值,没有可寻址存储,只能放右边。判别方法:能否对它取地址 &

正反例(建立直觉)

  • 正例1(常见左值):变量 a、数组元素 arr[0]、解引用 *p、结构体成员 st.member
  • 正例2(常见右值):常量 5、运算结果 a+b、函数返回值 f()
  • 正例3(判别)&a 合法 → a 是左值;&(a+b) 非法 → a+b 是右值
  • 正例4++a 返回的还是 a 这个对象 → 左值;a+1 产生临时副本 → 右值
  • 反例1:数组名是左值但不能赋值arr = other; 非法,常量地址)
  • 反例2:const 变量是左值但不能写c = 10; 非法,只读)

易混对比

左值 右值
本质 有可寻址的存储 临时值 / 纯值
能取地址 & ✅ 能 ❌ 不能
能放赋值号左边 ✅ 能 ❌ 不能
例子 变量、数组元素、*p、成员 常量、运算结果、函数返回值

变体验证(3 题,全过=学会)

  1. int a; int *p = &a;*p 左值(可 *p = 5);++a 左值(结果还是 a 这个对象)
  2. 陷阱题:数组名 arr左值,但不能 arr = other;(常量地址,不可赋值)
  3. 陷阱题:const int c = 5;左值(有地址可 &),但不能 c = 10;(只读)

口述要点(面试怎么讲)

  • 结论先行:能取地址/能放左边 = 左值;否则 = 右值
  • 为什么 ++a 是左值、a+1 是右值++a 修改并返回 a 这个对象本身(可寻址);a+1 产生一个临时副本,不可取地址
  • 赋值表达式 a = b 本身是左值(不是右值!)——所以 a = b = c 才能连等:赋值是右结合,先算 b = c(结果仍可寻址),再赋给 a
  • 左值 ≠ 可赋值:数组名(常量地址)和 const 变量(只读)都是左值但不能写
  • 寄存器宏是左值(*(volatile uint32_t*)0x40021000) = 1; 合法正因外层括号让 *解引用 成为左值,可写
  • 易错点:把"能放左边"当成"左值"的充要条件;以为 &a 是左值(它是右值)

关系网络

相邻概念 和本主题的关系 孤立理解会犯的错
指针 *p 解引用是左值;&a 的结果是右值 以为解引用只能读
数组名 数组名是左值但不可赋值(常量地址) 以为左值都能赋值
const const 变量是只读左值(可 & 不可写) 以为 const 不是左值
volatile 寄存器 寄存器宏是左值才能被写 忘了左值=可写是寄存器的前提

学习日期

2026-08-03


每主题一页,复习时只翻本目录。