Value categories
Value categories
C中的每个表达式(带有参数的运算符,函数调用,常量,变量名等)都由两个独立的属性表征:一个类型和一个值类别。
每个表达式都属于三个值类别之一:左值,非左值对象(右值)和函数指示符。
左值表达式
Lvalue表达式是任何具有与该类型不同的对象类型的表达式void
,它可能指定一个对象(如果左值在计算时没有实际指定对象,那么该行为是未定义的)。换句话说,左值表达式评估为对象身份
。此值类别的名称(“左值”)具有历史意义,反映了在CPL编程语言中使用左值表达式作为赋值运算符的左侧操作数。
左值表达式可用于以下左值上下文中
:
- 作为地址运算符的操作数(除非左值指定了一个位域或被声明为寄存器)。
如果在除sizeof
,_Alignof
或上面列出的运算符之外的任何上下文中使用了左值表达式,则任何完整类型的非数组左值都会进行左值转换,该值会模拟对象值的存储器负载。同样地,在比其他任何上下文中使用时阵列的左值经历阵列到指针转换sizeof
,_Alignof
,操作者从一个字符串数组初始化地址。
const / volatile / restrict-qualifiers和原子类型的语义只适用于左值(左值转换去除限定符并删除原子性)。
以下表达式是左值:
- 标识符,包括函数参数,只要它们被声明为指定对象(而不是函数)
可修改的左值表达式
一个可修改的左值
是完整非数组类型的非常量限定的左值表达式,如果它是结构体/联合体,则不具有常量限定的成员,即递归。
只有可修改的左值表达式可以用作递增/递减的参数,以及作为赋值和复合赋值操作符的左侧参数。
非左值对象表达式
通俗地称为rvalues
,非左值对象表达式是不指定对象的对象类型的表达式,而是没有对象标识或存储位置的值。无法取得非左值对象表达式的地址。
以下表达式是非左值对象表达式:
- 整数,字符和浮点常量
作为一种特殊情况,类型的表达式void
被假定为非左值对象表达式,它产生一个没有表示并且不需要存储的值。
请注意,具有数组类型成员(可能嵌套)的struct / union rvalue事实上指定了具有临时生存期的对象。该对象可以通过索引数组成员或通过数组成员的指针转换所获得的指针间接形成的左值表达式来访问。
函数指示符表达式
函数指示符(由函数声明引入的标识符)是函数类型的表达式。当在除address-of运算符,sizeof和_Alignof之外的任何上下文中使用时(最后两个在应用于函数时会生成编译错误),函数标识符总是被转换为非左值指针来运行。请注意,函数调用操作符是为指向函数的指针定义的,而不是函数指示符本身。
参考
- C11标准(ISO / IEC 9899:2011):