c++ - C 和 C++ 关于++ 运算符的区别

标签 c++ c increment prefix

我一直在胡闹一些代码,看到了一些我不明白“为什么”的东西。

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 += 1ptr1 的值计算之后进行的。 += 执行的赋值在 ptr += 1 的值计算之前进行排序,并且 += 所需的所有值计算都是必须在该分配之前排序。因此,这里的顺序是明确定义的,没有未定义的行为。

关于c++ - C 和 C++ 关于++ 运算符的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25654339/

相关文章:

javascript - 括号重要吗?

c++ - Qt Web 引擎获取历史记录

c - 在 GCC 中编译时使用 `-Wextra` 标志的缺点

sql - MySql INSERT MAX()+1 的问题

c - unix gcc 文件覆盖

用gcc编译C文件得到x86汇编代码

C++如何增加For循环增量

c++ - 特征矩阵库系数模运算

c++ - sscanf 中 uint16_t 的正确且可移植的 (Clang/GCC) 修饰符是什么?

c++ - 外部常量指针的常量正确性