rvalue定义是无法赋值的对象,但为什么文字是左值?

时间:2012-09-07 16:47:44

标签: c literals lvalue rvalue

所以我正在审查我们即将推出的主题,并且我已经来到了左右和右值,虽然这个定义让我感到困惑。为什么文字是左值?

“rvalue是指存储在内存中某个地址的数据值。右值是一个不能赋值给它的表达式”

“左值的原始定义是指”可以出现在赋值左侧的对象。“但是,const对象是左值,但它们不能出现在赋值的左侧。 “

3 个答案:

答案 0 :(得分:4)

C中有三类不可赋值的左值:const个对象,数组(以及成员为const或数组的对象)和不完整类型的表达式。

字符串文字是数组(我的意思是:字符串文字表达式引用的对象是数组)。这使他们成为左撇子。

非正式地,左值是一个引用一个对象的表达式,一个字符串文字是一个对象。


如果您想在C中正确定义左值,请参阅标准。在C99(6.3.2.1)中:

  

左值是具有对象类型或不完整类型的表达式   除了虚空;如果左值在评估时没有指定对象,   行为未定义。

脚注:

  

名称''左值''最初来自赋值表达式E1   = E2,其中左操作数E1需要是(可修改的)左值。它可能更好地被视为代表一个对象   ''定位器值''

因此,出现在作业的LHS上与其无关,除了lvalue用于表示其他东西的事实,除了标准C以外的某种语言。

您可能认为通过该正式定义,整数常量5也应该是左值表达式:它是一个表达式(特别是一个主表达式),它有一个对象类型(int是一种对象类型)。评估表达式5当然是有效的,所以如果它是左值,那么它必须“指定一个对象”。

这与address-of运算符的定义相矛盾,后者表示其操作数可能是指定对象的左值表达式。编译器拒绝&5,通常会显示一条错误消息,指出5 不是左值。

我认为答案在于6.5.1,它列出了不同类型的primary-expression,包括常量。对于每种其他类型的primary-expression,它表示在什么条件下它是左值。对于常数,它显然没有说什么,表明它们不是左值。但通常在C标准中,“An X ”形式的文本, X 斜体,是术语X的定义。所以我认为标准可以更清楚。

更新:n1570(C11的最新草案)中的文字是,我的重点是:

  

左值是一个表达式(对象类型不是void)   可能指定一个对象

C89(3.2.2.1)中的等效文字说“指定一个对象”[感谢hvd]。这告诉我,标准的作者对文本也不满意。常量不能指定对象,因此在此定义下,数字常量肯定是而不是左值。

答案 1 :(得分:1)

左值的非正式定义基本上是任何可以引用对象的表达式(在C意义上,占用内存的任何东西),以便可以读取或修改对象的值。您可能应用一元&运算符的任何内容都是左值。

不幸的是,你有一些表达式可以引用内存中的对象,但语义是这样的,你不能通过该表达式修改该对象的值。这包括数组表达式(包括字符串文字),const的表达式 - 限定类型和不完整类型的表达式。

最后一种类型的示例如下所示:

struct foo;
struct foo *fooptr;

表达式*fooptr是一个类型不完整的表达式; struct foo尚未完全定义。

所以我们有可修改的不可修改的左值。 可修改的左值可能是作业的目标。

字符串文字是不可修改的左值,因为它是数组类型表达式(字符串文字存储为char的数组,以便内存对整个程序可见,并且从程序启动到终止,数组的语义使得数组表达式可能不是赋值的目标。这是 numeric 文字或单个字符常量的不同情况,它们不引用内存中的项目。

答案 2 :(得分:0)

rvalues被定义为没有名称或的东西,你不能把或临时的地址。

这些天原来的定义已不再有效。您可以获取左值的地址,但不能使用右值的地址,这对我来说是最容易区分的。

如果你不能得到它的地址,那么它就是一个右值。