深入 C 语言: lvalue
目录
本文部分内容翻译自 c99 specification[1],如果觉得不妥的地方可以查看原文了解更加明确的见解
¶概述
lvalue
在 C99 规范中将其称为「定位符值」(locator value
),其概念最初是由赋值表达式E1=E2
引起,此赋值等式的左操作数E1
必须是可修改的(modifiable)lvalue
,将lvalue
看作对象(object)的定位符更加清晰。rvalue
在 C99 规范中描述为「表达式的值」(value of an expression
)
一种明显使用lvalue
的例子就是对象的标志符(identifier of an object)。
再举一个例子,如果E
是一个一元表达式,是一个指向对象的指针,*E
就是一个lvalue
,它指定了(designates)E
所指向的对象。
lvalue
是一个对象类型(object type)不是void
的表达式,它可能指定了一个对象。如果lvalue
在使用时并没有指定(designate)一个对象,这是一种未定义行为(undefined behavior)。当我们说一个对象具有特定类型时,类型被指向对象的lvalue
所规定。
❓ 有哪些操作数(Operand)是可修改的lvalue
?
lvalue
除了是 sizeof
操作符、_Alignof
操作符、一元取址及间接运算(Address and indirection operators)&
操作符、++
操作符、—-
操作符、.
操作符的左操作数(left operand)或赋值操作符=
的操作数时,非数组类型的lvalue
会被转换为存储在指定对象中的值,此时不再代表lvalue
,这种行为称为「定位符值转换」(lvalue conversion)。
❓ lvalue conversion
是如何转换的?哪些情况下是 UB(Undefined Behavior)的?
lvalue
除了是 sizeof
操作符、_Alignof
操作符、一元&
操作符的操作数或者是使用字符串字面量(string literal)初始化数组的操作数,具有「数组类型」(array of type)的表达式会被转换为类型为「指向类型的指针」(pointer to type)的表达式,该表达式指向数组对象的初始元素,并且不是lvalue
。如果数组对象具有寄存器存储类,则当前操作是未定义行为。