C++ 为什么字符串文字是l值,而所有其他文字都是r值?

C++ 为什么字符串文字是l值,而所有其他文字都是r值?,c++,c,literals,string-literals,C++,C,Literals,String Literals,C++03 5.1主要表达式§2说: 文本是一个主要表达式。其类型取决于其形式(2.13)。字符串文字是左值;所有其他文字都是右值 类似地,C99 6.5.1第4节规定: 字符串文字是主表达式。它是一个左值,类型如6.4.5所述 这背后的理由是什么 据我所知,字符串文字是对象,而所有其他文字则不是。l值总是指一个对象 但接下来的问题是,为什么字符串文字是对象,而所有其他文字都不是?在我看来,这个理由更像是鸡蛋或鸡的问题 我理解这个问题的答案可能与硬件体系结构有关,而不是与C/C++作为编程语言有

C++03 5.1主要表达式§2说:

文本是一个主要表达式。其类型取决于其形式(2.13)。字符串文字是左值;所有其他文字都是右值

类似地,C99 6.5.1第4节规定:

字符串文字是主表达式。它是一个左值,类型如6.4.5所述

这背后的理由是什么

据我所知,字符串文字是对象,而所有其他文字则不是。l值总是指一个对象

但接下来的问题是,为什么字符串文字是对象,而所有其他文字都不是?在我看来,这个理由更像是鸡蛋或鸡的问题


我理解这个问题的答案可能与硬件体系结构有关,而不是与C/C++作为编程语言有关,不过我还是希望听到相同的答案。

字符串文字是具有数组类型的文字,在C中,数组类型除了作为左值外,不可能存在于表达式中。字符串文本可以被指定为指针类型(而不是通常衰减为指针的数组类型)指向字符串“contents”,但这会使它们不太有用;特别是,
sizeof
运算符无法应用于它们


请注意,C99引入了复合文字,它们也是左值,因此将文字作为左值不再是特殊的例外;这更接近于常态。

我猜最初的动机主要是一个实用的动机:一根弦 文字必须驻留在内存中并具有地址。字符串的类型 literal是数组类型(
char[]
在C++中,
char const[]
在C++中),并且 在大多数上下文中,数组类型转换为指针。语言可以 已经找到了其他方法来定义它(例如,字符串文字可能有 首先是指针类型,有关于它的特殊规则 指向),但仅将文字设置为左值可能是
定义具体需要什么的最简单方法 <代码> LValue/Cuff>不总是引用对象。它也可以引用函数。此外,对象不必由
左值
引用。它们可能被代码> > Reals>代码>引用,包括数组(C++和C)。但是,在旧的C89中,数组到指针的转换不适用于
r值
数组

现在,
rvalue
表示没有、有限或即将到期的生命周期。但是,字符串文字对于整个程序有效

因此
字符串文本
作为
左值
是完全正确的。

字符串文本是数组-具有固有不可预测大小的对象(即用户定义的,可能较大的大小)。在一般情况下,除了作为内存中的对象(即
lvalues
)之外,没有其他方法来表示这些文本。在C99中,这也适用于复合文本,它们也是
左值

任何试图在语言层面上人为隐藏字符串文本是
左值这一事实的尝试都会产生大量完全不必要的困难,因为使用指针指向字符串文字的能力以及作为数组访问它的能力在很大程度上取决于它的左值在语言级别上是可见的

同时,标量类型的文本具有固定的编译时大小。同时,这些文本很可能直接嵌入到给定硬件体系结构上的机器命令中。例如,当您编写类似于
i=i*5+2
的代码时,文本值
5
2
成为生成的机器代码的显式(甚至隐式)部分。它们不存在,也不需要作为数据存储中的独立位置存在。在数据存储器中存储值
5
2
是毫无意义的

还值得注意的是,在许多(如果不是大多数或所有)硬件体系结构上,浮点文本实际上被实现为“隐藏的”
左值(即使该语言没有公开它们)。在x86这样的平台上,来自浮点组的机器命令不支持嵌入的立即数操作数。这意味着几乎每个浮点文本都必须由编译器存储在(并从)数据内存中读取。例如,当您编写类似
i=i*5.5+2.1
的内容时,它会被转换为

const double unnamed_double_5_5 = 5.5;
const double unnamed_double_2_1 = 2.1;
i = i * unnamed_double_5_5 + unnamed_double_2_1;

换句话说,
浮点文本
通常在内部变成“非官方的”
左值。然而,语言规范并没有试图公开这个实现细节,这是非常合理的。在语言级别上,
算术文本
更有意义,因为
右值

左值不是对象。左值是可以出现在赋值左侧的值,例如变量、结构成员和数组元素查找。(左)Dashwuff:委员会要求不同意见。根据6.3.2.1,“左值是具有对象类型或除void以外的不完整类型的表达式;如果左值在评估时未指定对象,则行为未定义。”根据该引用中引用的脚注(53),左值应被视为“对象定位值”。@JohnCalsbeek C++11“修复”了该问题,例如,
别名{}
现在可以使用了<如果
U
的类定义中声明了
arr
,则code>U{}.arr
也是数组类型的右值。顺便说一句,左值的更好近似值是“语法上有效的
运算符的操作数”。我怀疑这个定义实际上等同于标准的定义,除非我遗漏了什么……更新:它只是一个近似值。寄存器存储类对象作为
&
的操作数无效,但为左值。另外,我对什么也不清楚