4

所以我正在回顾我们即将到来的主题,我遇到了左值和右值,尽管定义让我感到困惑。为什么文字是左值?

“右值是指存储在内存中某个地址的数据值。右值是一个表达式,不能为其分配值”

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

4

3 回答 3

4

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

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

非正式地,左值是引用对象的表达式,而字符串字面量是对象。


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

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

带脚注:

名称“左值”最初来自赋值表达式 E1 = E2,其中要求左操作数 E1 是(可修改的)左值。将其视为表示对象“定位器值”可能更好</p>

因此,出现在赋值的 LHS 上与它无关,除了在标准 C 以外的其他语言中,左值曾经意味着别的东西。

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

这将与地址操作符的定义相矛盾,该定义说它的操作数可能是一个指定对象的左值表达式。编译器拒绝&5,通常带有一条错误消息,说明5不是左值。

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

更新:n1570(C11 的后期草案)中的文本是,我的重点是:

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

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

于 2012-09-07T16:54:56.777 回答
1

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

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

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

struct foo;
struct foo *fooptr;

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

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

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

于 2012-09-07T23:18:08.880 回答
0

右值被定义为没有名称或您无法获取其地址或临时地址的事物。

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

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

于 2012-09-07T16:50:08.900 回答