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

时间:2012-04-04 03:23:13

标签: c++ c literals string-literals

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

  

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

这背后的理由是什么?
据我所知,字符串文字是对象,而所有其他文字都不是。并且l值总是指对象。

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

我理解这个问题的答案可能与硬件架构有关,而不是C / C ++作为编程语言,但我想听到同样的看法。

注意:我正在将此问题标记为c& c ++既因为C99标准也有类似的引用,特别是§6.5.1.4

4 个答案:

答案 0 :(得分:31)

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

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

答案 1 :(得分:11)

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

任何试图人为地隐藏字符串文字在语言级别lvalues这一事实的尝试都会产生相当多的完全不必要的困难,因为能够指向带有指针的字符串文字以及能力以数组的形式访问它主要依赖于它在语言层面上可见的左值。

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

值得注意的是,在许多(如果不是大多数或全部)硬件架构中,浮点文字实际上实现为“隐藏”lvalues(即使语言不公开它们)。在像浮动组的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;

换句话说,floating-point literals通常最终会在内部成为“非官方”lvalues。但是,语言规范没有尝试公开此实现细节,这是完全合理的。在语言层面,arithmetic literals更有意义rvalues

答案 2 :(得分:9)

C ++中的lvalue并不总是引用一个对象。它也可以指一个功能。此外,lvalues不必引用对象。它们可以由rvalues引用,包括数组(在C ++和C中)。但是,在旧的C89中,数组到指针的转换不适用于rvalues数组。

现在,rvalue表示没有,有限或很快就会过期。但是,字符串文字适用于整个程序。

因此string literals lvalues完全正确。

答案 3 :(得分:6)

我猜原来的动机主要是一个实用的动词:一个字符串 文字必须驻留在内存中并具有地址。字符串的类型 literal是一种数组类型(C中为char[],C ++中为char const[]) 数组类型在大多数上下文中转换为指针。语言可以 已找到其他方法来定义它(例如字符串文字可能有 指针类型开头,有关于它的特殊规则 指向),但只是使文字成为左值可能是 最简单的方法来定义具体需要的东西。

相关问题