为什么在C ++中允许多个预增量而在C中不允许?

时间:2018-01-11 09:10:46

标签: c++ c language-lawyer

为什么

int main()
{
    int i = 0;
    ++++i;
}

有效的C ++但不是有效的C?

4 个答案:

答案 0 :(得分:44)

C和C ++对前缀++的结果说了不同的话。在C ++中:

[expr.pre.incr]

  

前缀++的操作数通过添加1来修改。操作数应为   可修改的左值。操作数的类型应为算术运算   除了cv bool之外的类型,或者指向完全定义的对象的指针   类型。 结果是更新的操作数;它是一个左值,它是一个   如果操作数是位字段,则为位字段。表达式++ x是   相当于x + = 1。

所以++可以再次应用于结果,因为结果基本上只是递增的对象并且是左值。但是在C中:

6.5.3 Unary operators

  

前缀增量或减量运算符的操作数应具有原子,限定或非限定的实数或指针类型,并且应为可修改的左值。

     

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

结果不是左值;它只是增量的纯值。所以你不能应用任何需要左值的运算符,包括++。

如果您被告知C ++和C是彼此的超集或子集,请知道情况并非如此。有许多不同之处使得该断言错误。

答案 1 :(得分:14)

在C中,一直都是这样。可能是因为预先递增的++可以针对许多CPU上的单个机器代码指令进行优化,包括20世纪70年代开发++概念时的指令。

在C ++中虽然存在运算符重载的对称性,但需要考虑。要匹配C,规范的预增量++将需要返回const &,除非您对用户定义和内置类型(这将是一种气味)有不同的行为。限制返回const &是一种设计。所以++的返回从C规则中放松,代价是增加了编译器的复杂性,以便利用内置类型的任何CPU优化。

答案 2 :(得分:4)

我假设您理解为什么它在C ++中没问题,所以我不打算详细说明。

无论它的价值如何,这都是我的测试结果:

t.c:6:2: error: lvalue required as increment operand
  ++ ++c;
  ^

关于CppReference

  

非左值对象表达式

     

通常称为rvalues,非左值对象表达式是不指定对象的对象类型的表达式,而是没有对象标识或存储位置的值。无法获取非左值对象表达式的地址。

     

以下表达式是非左值对象表达式:

     
      
  • 未指定所有运营商返回左值,包括

         
        
    • 递增和递减运算符(注意:预处理是C ++中的左值)
    •   
  •   

和n1570的第6.5.3.1节:

  

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

因此在C中,前缀增量和前缀减量运算符的结果不需要是左值,因此不能再次递增。事实上,这样的词可以理解为"要求是rvalue"。

答案 3 :(得分:2)

其他答案解释了标准在他们需要的方面有所不同的方式。这个答案在差异方面提供了一个激励性的例子。

在C ++中,你可以拥有像int& foo(int&);这样的函数,它在C中没有模拟。对于C ++来说,选择foo(foo(x));是有用的(而不是繁重的)。

想象一下,基本类型的操作是在某处定义的,例如: int& operator++(int&);++++x本身并不是一个激励性的例子,但它符合上述foo的模式。