为什么多个增量/减量在C ++中有效但在C中不有效?

时间:2013-02-10 14:52:27

标签: c++ c language-lawyer lvalue incompatibility

测试。(C / CPP)

#include <stdio.h>

int main(int argc, char** argv)
{
  int a = 0, b = 0;
  printf("a = %d, b = %d\n", a, b);
  b = (++a)--;
  printf("a = %d, b = %d\n", 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)--操作吗?有没有人对此有任何见解?

4 个答案:

答案 0 :(得分:13)

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

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

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

编辑:跟进@ bames53评论。它是C ++ 98 / C ++ 03中未定义的行为,但C ++ 11中关于序列点概念的变化现在定义了这个表达式。

答案 1 :(得分:3)

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

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

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

在C ++ 03中,(++a)--会导致未定义的行为,因为两个相互之间没有排序的操作正在修改同一个变量。 (即使一个是“前”,一个是“发布”,但它们没有排序,因为没有,&&?等。)

在C ++ 11中,表达式现在可以满足您的期望。但是C11并没有改变任何这样的规则,这是一个语法错误。

答案 2 :(得分:2)

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

  

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

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

  

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

[重点补充,两种情况下]

另请注意,虽然(++a)--aint时提供了未定义的行为(至少在C ++ 03中),但a是某些用户定义的类型,所以你使用自己的++--重载,将定义行为 - 在这种情况下,你得到相当于:

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

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

答案 3 :(得分:0)

§5.2.7增量和减量:

  

post fi x ++表达式的值是其操作数的值。 [...] 操作数应为可修改的左值

C编译中出现的错误有助于表明这只是C ++中的一个功能。