所以我正在审查我们即将推出的主题,并且我已经来到了左右和右值,虽然这个定义让我感到困惑。为什么文字是左值?
“rvalue是指存储在内存中某个地址的数据值。右值是一个不能赋值给它的表达式”
“左值的原始定义是指”可以出现在赋值左侧的对象。“但是,const对象是左值,但它们不能出现在赋值的左侧。 “
答案 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被定义为没有名称或的东西,你不能把或临时的地址。
这些天原来的定义已不再有效。您可以获取左值的地址,但不能使用右值的地址,这对我来说是最容易区分的。
如果你不能得到它的地址,那么它就是一个右值。