int main()
{
int i=3;
(++i)++;
printf("%d",i);
}
该程序适用于 g++ 编译器,但不适用于 gcc。如果我写 i++++ 或 ++i++ 它在 cpp 中也不起作用。我认为 c-expression 和 c++-expression 之间存在差异。有人可以解释一下 L 值和 R 值吗?
int main()
{
int i=3;
(++i)++;
printf("%d",i);
}
该程序适用于 g++ 编译器,但不适用于 gcc。如果我写 i++++ 或 ++i++ 它在 cpp 中也不起作用。我认为 c-expression 和 c++-expression 之间存在差异。有人可以解释一下 L 值和 R 值吗?
编辑:这个答案对于更新的问题是不正确的,它适用于最初陈述的问题。
(i++)++
不应该与 gcc 或 g++ 一起使用,无论他们是否在两种语言中将文件解析为 C 或 C++ 后缀增量都需要一个左值作为操作数,结果是一个右值。
(请注意,右值仅在 C++ 中正式使用。在 C 中,表达式的结果要么是显式左值,要么不是左值。术语右值根本没有在 C 标准的规范文本中使用。)
简单地说,左值是一个引用对象的表达式,即概念上某个地方的存储区域。可修改的左值是可以赋值的有效值,因此可以出现在赋值表达式的左侧。
右值只是一个值,您可以从中分配可修改的左值,但不能分配给您。它只能出现在赋值表达式的右侧。
g++
给我错误:lvalue required as increment operand
。
前缀增量(和减量)略有不同。在 C++ 中,前缀增量的结果是明确的左值(5.3.2/1 [expr.pre.incr]);在 C 中,它明确不是左值(6.5.3.1 声明 ++E 等价于 (E+=1);6.5.16 表示任何赋值的结果都不是左值)。
(++i)++
因此,仅在 C++ 中在语义上是正确的,但是它具有未定义的行为,因为您将一个值存储到一个对象两次而没有中间的序列点。
来自维基:
一些语言使用左值和右值的概念。左值是具有可被正在运行的程序以编程方式访问的地址的值(例如,通过一些地址操作符,如 C++ 中的“&”),这意味着它们是变量或对某个内存位置的取消引用。右值可以是左值(见下文)或非左值——这个术语仅用于与左值区分开来。在 C 语言中,术语左值最初表示可以赋值的东西(来自左值,表示它位于赋值运算符的左侧),但由于语言中添加了“const”,现在称为'可修改的左值'。
$5.2.6-
通过应用后缀 ++ 获得的值是操作数在应用运算符之前的值。[注:得到的值是原值的副本] 操作数应为可修改的左值。操作数的类型应为算术类型或指向完整对象类型的指针。记下结果后,对象的值被修改为加 1,除非对象是 bool 类型,在这种情况下它被设置为 true。[注意:不推荐使用此用法,请参阅附件 D。]结果是一个右值。结果的类型是操作数类型的 cv 非限定版本。另见 5.7 和 5.17。
$5.3.2/1-
“前缀 ++ 的操作数通过加 1 进行修改,如果为 bool,则设置为 true(不推荐使用此用法)。操作数应为可修改的左值。 ”
这应该可以解释您在 C++ 中遇到的错误。