C语言中赋值语句左侧(LHS)的求值规则解析
关于C语言赋值表达式左侧求值的疑问与解析
我的学习框架与背景认知
我正通过语法(syntax)、语义(semantics)、习语(idioms)三个核心维度学习C语言指针,聚焦表达式(expression)、值(value)、求值(evaluation)、**赋值(assignment)**这些基础概念,已建立的语义模型如下:
- 表达式:需求值的语句,例如
10 + (15 - 2 * 5)最终求值为15 - 值:自身即为求值结果的元素,用⟦x⟧表示“x求值为”,例如⟦15⟧ = 15、⟦
⟧ = - 求值:将表达式简化为值的过程,遵循“函数需参数为值才执行”等规则
- 赋值:将左侧名称映射到右侧求值后的结果,右侧需先求值为值(例如
int a = 5 + 3先求值为8,再存入内存,存储操作是赋值的副作用而非结果值) - 变量与指针求值规则:右侧变量求值为其存储的值(如
int a=5时⟦a⟧→5);指针存储地址值,&和*运算符规则:⟦&a⟧→,⟦*ptr⟧→对应地址存储的值
遇到的问题
此前我认为赋值只需求值右侧、忽略左侧,但遇到以下代码时,原模型无法解释:
int arr[5]={1,2,3,4,5}; int *ptr=arr; *(ptr+1)=*ptr;
这里左侧的*(ptr+1)似乎需要求值,搞不懂左侧为何需要求值及具体运行机制。
结合语义模型的解析
首先要修正认知:C语言中赋值表达式的左侧并非“忽略求值”,而是要求求值为一个“左值(lvalue)”——左值是一种特殊的表达式结果,它代表一个可被修改的内存位置(普通求值结果是“右值(rvalue)”,即单纯的值)。
结合你的语义模型,拆解*(ptr+1)=*ptr的完整运行过程:
- 右侧求值:
*ptr按照规则⟦*ptr⟧→对应地址的值,这里ptr指向arr[0],所以⟦*ptr⟧→1,得到右值1 - 左侧求值:
- 先计算
ptr+1:ptr存储arr[0]的地址,指针加法求值为偏移后的地址,即⟦ptr+1⟧→<arr[1]的地址> - 再对
*(ptr+1)求值:这里的*运算符针对指针地址,求值结果不是单纯的值,而是代表arr[1]内存位置的左值——可以理解为⟦*(ptr+1)⟧→<可修改的内存位置:arr[1]>
- 先计算
- 赋值操作:将右侧的右值1,通过左侧的左值指向的内存位置完成存储(这就是你所说的赋值副作用),同时整个赋值表达式的结果值是右侧的1(但通常我们不会用到这个结果)
补充完善你的语义模型:
- 求值过程不仅能得到普通值(右值),还能得到左值——左值是一种“指向内存位置的标识”,是赋值左侧必须满足的条件
- 指针表达式
*(ptr + n)的求值结果分场景:如果出现在赋值右侧(如int b = *(ptr+1)),则会进一步从该内存位置取出值,得到右值;如果出现在左侧,则保留为指向内存位置的左值
内容的提问来源于stack exchange,提问作者Ghassen
相关产品推荐
相关产品推荐

