为什么 "++i++" 无效而 (++i)++ 有效?
Why is "++i++" invalid while (++i)++ is valid?
让我们考虑以下代码:
int main() {
int i = 2;
int b = ++i++;
return 3;
}
编译时出现以下错误:
<source>: In function 'int main()':
<source>:3:16: error: lvalue required as increment operand
3 | int b = ++i++;
| ^~
这听起来很公平。后缀自增优先级高于前缀自增,所以代码被解析为int b = ++(i++);
,i
是一个右值。因此错误。
现在让我们考虑使用括号覆盖默认优先级的变体:
int main() {
int i = 2;
int b = (++i)++;
return 3;
}
此代码编译 returns 3. 就其本身而言,这对我来说听起来很公平,但似乎与第一个代码矛盾。
问题:为什么 (++i)
是 lvalue
而 i
不是?
谢谢!
更新: 上面显示的错误消息来自 gcc (x86-64 9.2)。这是确切的渲染:
error with gcc
Clang x86-64 9.0.0 有一个完全不同的信息:
error with clang
<source>:3:13: error: expression is not assignable
int b = ++i++;
^ ~~~
使用 GCC,您会觉得问题出在后缀运算符上,然后您可能会想为什么 ++i
可以,而 i
不行,因此我的问题。使用 Clang 更清楚问题出在前缀运算符上。
i
和 ++i
都是左值,但 i++
是右值。
++(i++)
无效,因为前缀 ++
被应用于 i++
,这是一个右值。但是 (++i)++
很好,因为 ++i
是一个左值。
请注意,在C 中,情况有所不同; i++
和 ++i
都是右值。 (这是一个例子,说明为什么人们应该停止假设 C 和 C++ 具有相同的规则。人们将这些假设插入到他们的问题中,然后必须反驳这些假设。)
so the code is parsed as int b = ++(i++); and i is an rvalue.
没有。 i
不是右值。 i
是一个左值。 i++
是一个右值(具体来说是右值)。
这个声明
int b = ++i++;
相当于
int b = ++( i++ );
后缀递增运算符return是递增前操作数的值。
来自 C++ 17 标准(8.2.6 递增和递减)
1 The value of a postfix ++ expression is the value of its
operand...The result is a prvalue.
而一元递增运算符 return 是递增后的左值。所以这个声明
int b = (++i)++;
有效。例如,您可以写
int b = (++++++++i)++;
来自 C++ 17 标准(8.3.2 递增和递减)
1 The operand of prefix ++ is modified by adding 1. The operand shall
be a modifiable lvalue. The type of the operand shall be an arithmetic
type other than cv bool, or a pointer to a completely-defined object
type. The result is the updated operand; it is an lvalue, and it is a
bit-field if the operand is a bit-field....
注意在 C 中,两个运算符 return 都是一个值而不是左值。所以在 C 中这个声明
int b = (++i)++;
无效。
让我们考虑以下代码:
int main() {
int i = 2;
int b = ++i++;
return 3;
}
编译时出现以下错误:
<source>: In function 'int main()':
<source>:3:16: error: lvalue required as increment operand
3 | int b = ++i++;
| ^~
这听起来很公平。后缀自增优先级高于前缀自增,所以代码被解析为int b = ++(i++);
,i
是一个右值。因此错误。
现在让我们考虑使用括号覆盖默认优先级的变体:
int main() {
int i = 2;
int b = (++i)++;
return 3;
}
此代码编译 returns 3. 就其本身而言,这对我来说听起来很公平,但似乎与第一个代码矛盾。
问题:为什么 (++i)
是 lvalue
而 i
不是?
谢谢!
更新: 上面显示的错误消息来自 gcc (x86-64 9.2)。这是确切的渲染: error with gcc
Clang x86-64 9.0.0 有一个完全不同的信息: error with clang
<source>:3:13: error: expression is not assignable
int b = ++i++;
^ ~~~
使用 GCC,您会觉得问题出在后缀运算符上,然后您可能会想为什么 ++i
可以,而 i
不行,因此我的问题。使用 Clang 更清楚问题出在前缀运算符上。
i
和 ++i
都是左值,但 i++
是右值。
++(i++)
无效,因为前缀 ++
被应用于 i++
,这是一个右值。但是 (++i)++
很好,因为 ++i
是一个左值。
请注意,在C 中,情况有所不同; i++
和 ++i
都是右值。 (这是一个例子,说明为什么人们应该停止假设 C 和 C++ 具有相同的规则。人们将这些假设插入到他们的问题中,然后必须反驳这些假设。)
so the code is parsed as int b = ++(i++); and i is an rvalue.
没有。 i
不是右值。 i
是一个左值。 i++
是一个右值(具体来说是右值)。
这个声明
int b = ++i++;
相当于
int b = ++( i++ );
后缀递增运算符return是递增前操作数的值。
来自 C++ 17 标准(8.2.6 递增和递减)
1 The value of a postfix ++ expression is the value of its operand...The result is a prvalue.
而一元递增运算符 return 是递增后的左值。所以这个声明
int b = (++i)++;
有效。例如,您可以写
int b = (++++++++i)++;
来自 C++ 17 标准(8.3.2 递增和递减)
1 The operand of prefix ++ is modified by adding 1. The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a completely-defined object type. The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field....
注意在 C 中,两个运算符 return 都是一个值而不是左值。所以在 C 中这个声明
int b = (++i)++;
无效。