【问题标题】:Arrays in C - Lvalue vs. R-ValueC 中的数组 - 左值与右值
【发布时间】:2021-07-01 11:52:14
【问题描述】:

我对 C 中 lValues 和 rValues 的定义以及数组适合的位置有疑问: 我一直认为数组,例如

int arr[10];

是不可修改的左值。但是,如果您像可修改的 lValues 一样使用它们,例如这里:arr++;,并尝试编译它,我没有收到预期的错误消息。该消息是“需要作为增量操作数的左值”。对于其他不可修改的 lValue,例如常量,消息是“只读变量的增量”。 这是为什么呢?

【问题讨论】:

  • 具体的诊断信息是个别实现的功能;您必须询问编写该编译器的人为什么要使用这些特定消息。但请注意,常量不是不可修改的左值,它们是 rvalues (它们不指定内存位置),因此编译器可能会沿着不同的处理路径进行处理,因此它是错误消息不同也就不足为奇了。

标签: arrays c rvalue lvalue


【解决方案1】:

如果我们要尝试评估 arr++,那么 C 2018 6.3.2.1 3 会告诉我们 arr 首先被转换为指向其第一个元素的指针:

除非它是 sizeof 运算符的操作数,或一元 & 运算符,或者是用于初始化数组的字符串字面量,否则表达式的类型为“array of type” >”被转换为类型为“pointer to type”的表达式,它指向数组对象的初始元素,而不是左值……

因此,如果我们进行该转换然后处理++,我们会发现++ 的操作数只是一个值,而不是左值。因此会出现错误消息,即增量操作数需要左值。

当然,编译器可以给出不同的信息; C 标准对诊断消息中必须说明的内容并不严格。

【讨论】:

  • 一个值可以既不是左值也不是右值?我认为它必须是一个或另一个......
  • @Mary:C 标准使用术语“值”,而不是“右值”。您在哪里看到既不是左值也不是值的东西?该数组是一个左值。它被转换为指向其第一个元素的指针,从而产生一个值。不是左值的值不能是++ 的操作数。
  • 我说的既不是左值也不是 R 值……我的意思是我认为 C 标准值总是 R 值或 L 值……
  • @Mary:再一次,你在哪里看到既不是左值也不是右值的东西?
  • “所以,如果我们进行转换然后处理 ++,我们会发现 ++ 的操作数只是一个值,而不是左值。”所以它是一个值,但没有左值和右值,对吧?
【解决方案2】:

来自https://docs.microsoft.com/en-us/cpp/c-language/l-value-and-r-value-expressions?redirectedfrom=MSDN&view=msvc-160

以下任何 C 表达式都可以是左值表达式:

  • 整数、浮点、指针、结构或联合类型的标识符
  • 不计算为数组的下标 ([ ]) 表达式
  • 成员选择表达式(-> 或 .)
  • 不引用数组的一元间接 (*) 表达式
  • 括号中的左值表达式
  • 一个 const 对象(一个不可修改的左值)

我猜一个数组根本就不是左值。但是数组的下标(不是数组的数组!)是一个。

【讨论】:

  • 数组是左值。 Microsoft 文档是错误的。例如,一元 & 的操作数必须是函数指示符、[] 的结果、一元 * 的结果或左值 (C 2018 6.5.3.2 1)。但是您可以获取数组的地址,如&arr。那是因为arr确实是一个左值,因为它不是函数指示符,不是[]的结果,也不是一元*的结果,虽然你也可以得到一个数组左值作为[]的结果或一元*。数组很少用作左值,因为它们在大多数表达式中会自动转换为指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2017-12-03
  • 2019-04-09
相关资源
最近更新 更多