为什么
int main()
{
int i = 0;
++++i;
}
有效的C ++但不是有效的C?
答案 0 :(得分:44)
C和C ++对前缀++的结果说了不同的话。在C ++中:
前缀++的操作数通过添加1来修改。操作数应为 可修改的左值。操作数的类型应为算术运算 除了cv bool之外的类型,或者指向完全定义的对象的指针 类型。 结果是更新的操作数;它是一个左值,它是一个 如果操作数是位字段,则为位字段。表达式++ x是 相当于x + = 1。
所以++可以再次应用于结果,因为结果基本上只是递增的对象并且是左值。但是在C中:
前缀增量或减量运算符的操作数应具有原子,限定或非限定的实数或指针类型,并且应为可修改的左值。
前缀++运算符的操作数的值递增。的的 结果是增量后操作数的新值。
结果不是左值;它只是增量的纯值。所以你不能应用任何需要左值的运算符,包括++。
如果您被告知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
的模式。