【问题标题】:C How to identify rvalue and lvalue?C如何识别右值和左值?
【发布时间】:2012-06-19 16:27:24
【问题描述】:

在 C 中,有没有办法识别右值和左值?

其中一些很容易识别,比如在赋值中,左边的值是左值,右边的值是右值。

但在其他场景下,很难识别这样的规则。

例如:*p++i++(其中 p 是指向整数的指针,i 是整数) - 如何识别它是右值还是左值? 上下文是 ++*p++ 有效,而 ++i++ 无效,因为 i++ 是右值(正如严肃的人所说)。

如何识别表达式中的右值和左值?

【问题讨论】:

  • 我认为这是一个很好的问题,但您所说的“识别”是什么意思?您是否想要一个完整的操作列表以及它们是否返回 l 或 r 值?一种从函数信号中分辨的方法?一种查看每行包含左值或右值的代码的方法?
  • @djechlin,“识别”我的意思是,我是否可以通过查看源代码来确定代码片段是否有效(无需编译)。如果没有完整的列表,是否有可以用来识别 rvalue 和 lvalue 的方法?但是,如果存在一个完整的列表,那对我有用。
  • 我认为你应该从忘记“rvalue = value on the right”开始,这是完全错误的。
  • @qdii,我同意。但是如何辨别什么是对的呢?
  • lvalue and rvalue 的可能重复项

标签: c lvalue rvalue


【解决方案1】:

lvalue 一词一直与 C 一起使用(并被带到 C++ 并在以后扩展)。一开始就没有右值。我的草稿 (N1570) 确实列出了两次出现的术语 rvalue —— 一次在脚注 #64 中,一次在索引中。

简而言之:在 C 世界中,您有两种类型的对象 - 左值 和其他所有对象。

请注意,脚注不是标准的一部分,但它们可以提供一些有用的见解。这是脚注64:

64) 名称“左值”最初来自赋值表达式 E1 = E2,其中左 操作数 E1 必须是(可修改的)左值。它也许被认为是代表一个更好的 对象“定位器值”。本国际标准中描述了有时称为“右值”的内容 作为“表达式的值”。

左值的一个明显例子是对象的标识符。再举一个例子,如果 E 是一元 表达式是指向对象的指针,*E 是一个左值,指定 E 指向的对象。

这是一个好的开始。现在,请记住,表达式是由对象(和运算符,但我们稍后会介绍)构建的,在处理对象时需要担心两个基本的事情:类型和值。让我们看看标准对类型限制的说明(6.3.2.1/p1):

左值是一个表达式(对象类型不是 void),它可能 指定对象;64) 如果左值在计算时未指定对象,则行为未定义。

另外,请注意下一行很重要:

当一个对象被称为具有特定类型时,该类型是 由用于指定对象的左值指定。

因此,lvalue 可以用作类型的替代品(我们也会看到这一点)。接下来,让我们看看对象左值(6.3.2.1/2)的上下文:

当它是 sizeof 运算符的操作数时,_Alignof 运算符, 一元 & 运算符、++ 运算符、-- 运算符或 . 的左操作数。操作员 或赋值运算符

所以,这些是您需要留意的运算符。在所有其他情况下:

一个没有数组类型的左值被转换为 存储在指定对象中的值(不再是左值);这称为左值 转换。

有两种特殊类型:数组和函数指示符。这些衰减,即转换为类型为“pointer to type”的表达式,指向 指向数组对象的初始元素,并且不是左值 / “指向函数返回类型的指针”。 (请记住,我们已经暂停了 lvalues 可以作为类型工作的事实——这正是他们对 sizeof_Alignof 所做的事情!)

【讨论】:

    【解决方案2】:

    lvalue(来自左侧(LHS)值)指的是内存(或寄存器)存储并且您可以为其分配值。 *p++ 是一个左值,因为它是一个取消引用的指针(即指的是内存中ptr 指向的位置,而ptr 的值本身就是该位置的地址)和@ 987654324@ 实际上意味着:*ptr = *ptr + 1; ptr = ptr + 1; - 它递增ptr 指向的值,然后递增指针值本身。 i++ 不是 左值,因为它是 i 的值加 1,并且不引用内存中的位置。您可以将这些值视为最终值 - 它们不能进一步修改,只能用作分配给 lvalues 的值。这就是为什么它们被称为rvalues(来自右手边(RHS)值)。

    LHS 和 RHS 引用赋值表达式 A = B; 的两边。 A 是左轴,B 是右轴。

    【讨论】:

      【解决方案3】:

      来自 Deitel 和 Deitel:

      变量名被称为lvalues(表示“左值”),因为它们可以用在赋值运算符的左侧。常量被称为 rvalues(表示“正确的值”),因为它们只能用于赋值运算符的右侧。请注意,lvalues 也可以用作 rvalues,但反之则不行。

      x = 3;  /*  here, x is an lvalue */
      c = x;  /*  and in the next line it is an rvalue */
      

      【讨论】:

      • 听起来他知道这一点,并想知道更全面的方法来识别它们。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多