左值(lvalue) 是
B语言/
C语言/
C++语言等
类C语言中的一类
表达式。“左”(left)的原意是指可以放在赋值符号“=”的左边,但其实也表示能作为&和++等
操作符的
操作数(B语言中已经如此)。而且,现代
C/C++中的含义已经不局限于此。lvalue的l被重新解释为location。这也对应于ISO C11/ISO
C++11的内存位置(memory location)。
左值可以表示对象,即具有对应的可以由用户访问的
存储单元(应特别注意和类风格面向对象中的对象——类的实例的区别;
Java等语言的对象即使用此种说法;C的左值相当于Java中的“变量”)。正因为如此,用于取得对象的指针的内建
操作符&要求
操作数是左值。
左值表示存储在计算机
内存的对象,与此相对的概念是
右值(rvalue),习惯上统称为左值性(lvalue-ness) 。
可以出现在特定的
操作符中的一些
操作数需要是左值,如赋值(左操作数)、一元&、++和--。此外,
sizeof、alignof等操作数中可以出现左值,且不会发生以下提到的左值到非左值的转换。
左值参与决定
转换规则。除了需要左值的
上下文,左值可以转换为非左值。数组名和函数名作为
表达式除了表示其本身,可以转换为对应指针。这些在C中lvalue
conversion、array conversion和function conversion,对应于C++的lvalue-to-rvalue conversion、array-to-
pointer conversion和function-to-pointer conversion。后两者习惯上称为退化(decay) ,在
传递函数参数时尤其明显。这三个转换是C++的标准转换(
standard conversion)的子集,因为其左值转换成
右值的共性(注意函数名作为表达式在C++也是左值),在
函数重载规则中被称为左值变换(lvalue transformation) 。
B语言的左值和右值是
形式文法中的元素。而ISO
C/C++的左值和右值独立于语法,是纯粹语义上的概念。此外,ISO C在
脚注中约定右值就是值,但ISO
C++中右值和值是两个明确独立的概念。
ISO C允许不是左值也
不作为右值(即具有值)的表达式——函数指示符(function designator) ——也就是单独的函数名。它通过转换得到函数指针值。
ISO C/C++中,左值可以进一步分为可以修改的左值(modifiable lvalue) 和不可修改的左值。只有可修改的左值才能作为
赋值表达式的左
操作数。不可修改的左值的一类例子是具有const类型的左值。
注意左值可能表示对象。左值和
对象类型并无特定关联,ISO C99(以及之后的3个技术修正案)在此的定义有误,在ISO C11被修正。
左值和常量并不一定有必然的固定关联。常量在C语言中是语法元素,和C的
字符串字面量(string
literal)一起,对应于
C++的
字面量(literal) 。作为常量表达式,它可以是左值(如C++的字符串字面量,习惯上也被称为
字符串常量——尽管C的字符串字面量严格地不是常量),也可以是非左值(C的常量或C++的其它字面量)。注意这里的常量比数学中使用的通常意义上的概念严格得多,也不和变量直接相对。