为什么多个增量/递减在C++中有效,而在C中无效

Why are multiple increments/decrements valid in C++ but not in C?

本文关键字:有效 C++ 而在 无效 为什么      更新时间:2023-10-16

测试。(c/cpp)

#include <stdio.h>
int main(int argc, char** argv)
{
  int a = 0, b = 0;
  printf("a = %d, b = %dn", a, b);
  b = (++a)--;
  printf("a = %d, b = %dn", a, b);
  return 0;
}

如果我将上面的内容保存为.cpp文件,它会编译并在执行时输出:

a = 0, b = 0
a = 0, b = 1

然而,如果我把它保存为.c文件,我会得到以下错误:

test.c:7:12: error: lvalue required as decrement operator.

(++a)操作不应该在(newValue)--操作之前解决吗?有人对此有什么见解吗?

在C中,前缀和后缀递增/递减运算符的结果不是左值。

在C++中,后缀递增/递减运算符的结果也不是左值,但前缀递增/递减操作符的结果是左值。

现在,在C++中执行类似(++a)--的操作是未定义的行为,因为您要在两个序列点之间修改对象值两次。

编辑:关注@bames53评论。它在C++98/C++03中是未定义的行为,但C++11中对序列点思想的改变现在使这个表达式得到了定义。

在C和C++中,有一些左值表达式可以在=运算符的左侧使用,也有一些右值表达式可以不使用。C++允许更多的东西成为lvalue,因为它支持引用语义。

++ a = 3; /* makes sense in C++ but not in C. */

递增和递减运算符类似于赋值,因为它们可以修改参数。

在C++03中,(++a)--会导致未定义的行为,因为两个没有按顺序排列的操作正在修改同一个变量。(即使一个是"pre",一个是是"post",但它们是未排序的,因为没有,&&?等。)

在C++11中,表达式现在执行您所期望的操作。但C11并没有改变任何这样的规则,这是一个语法错误。

对于任何可能想要标准中所述差异的精确细节的人,C99§6.5.3/2说:

前缀++运算符的操作数的值递增。结果是新的递增后操作数的

相比之下,C++11,§5.3.2/1说:

结果是更新的操作数;它是一个左值,如果操作数是一个位字段。

[在这两种情况下都增加了强调]

还要注意,虽然(++a)--aint时给出了未定义的行为(至少在C++03中是这样),但如果a是某种用户定义的类型,因此您使用自己的++--重载,则行为将被定义——在这种情况下,您将得到等效的:

a.operator++().operator--(0);

由于每个操作符都会导致一个函数调用(不能重叠),因此实际上确实有序列点来强制定义行为(注意,我不建议使用它,只是注意在这种情况下行为实际上是定义的)。

§5.2.7增量和减量:

后置++表达式的值是其操作数的值[…] 操作数应为可修改的左值

您在C编译中遇到的错误有助于表明这只是C++中的一个功能。