我一直在胡闹一些代码,看到了一些我不明白“为什么”的东西。
int i = 6;
int j;
int *ptr = &i;
int *ptr1 = &j
j = i++;
//now j == 6 and i == 7. Straightforward.
如果你把运算符放在等号的左边呢?
++ptr = ptr1;
等价于
(ptr = ptr + 1) = ptr1;
而
ptr++ = ptr1;
等价于
ptr = ptr + 1 = ptr1;
后缀运行编译错误,我明白了。您在赋值运算符的左侧有一个常量“ptr + 1”。很公平。
前缀 one 在 C++ 中编译和工作。是的,我知道这很困惑,您正在处理未分配的内存,但它可以工作并编译。在 C 中,这不会编译,返回与后缀“需要左值作为赋值的左操作数”相同的错误。无论它是如何编写的,使用两个“=”运算符或使用“++ptr”语法扩展,都会发生这种情况。
C 处理这种赋值的方式与 C++ 处理它的方式有什么区别?
最佳答案
在 C 和 C++ 中,x++
的结果是一个右值,所以你不能给它赋值。
在 C 中,++x
等价于 x += 1
(C 标准 §6.5.3.1/p2;所有 C 标准引用均指向 WG14 N1570)。在 C++ 中,如果 x
不是 bool
(C++ 标准),则 ++x
等价于 x += 1
§5.3.2 [expr.pre.incr]/p1;所有 C++ 标准引用均来自 WG21 N3936)。
在 C 中,赋值表达式的结果是一个右值(C 标准 §6.5.16/p3):
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue.
因为它不是左值,所以不能分配给它:(C 标准 §6.5.16/p2 - 注意这是一个约束)
An assignment operator shall have a modifiable lvalue as its left operand.
在 C++ 中,赋值表达式的结果是左值(C++ 标准 §5.17 [expr.ass]/p1):
The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand.
所以 ++ptr = ptr1;
是 C 中可诊断的约束违规,但不违反 C++ 中的任何可诊断规则。
但是,在 C++11 之前,++ptr = ptr1;
具有未定义的行为,因为它在两个相邻序列点之间修改了两次 ptr
。
在 C++11 中,++ptr = ptr1
的行为得到了很好的定义。如果我们将其重写为
(ptr += 1) = ptr1;
自 C++11 起,C++ 标准规定 (§5.17 [expr.ass]/p1)
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.
所以 =
执行的赋值是在 ptr += 1
和 ptr1
的值计算之后进行的。 +=
执行的赋值在 ptr += 1
的值计算之前进行排序,并且 +=
所需的所有值计算都是必须在该分配之前排序。因此,这里的顺序是明确定义的,没有未定义的行为。
关于c++ - C 和 C++ 关于++ 运算符的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25654339/