在C,C ++,Java和C#中增加和增加运算符行为

免责声明: 这不是一个真实的例子。 这只是这些语言如何工作的理论问题。

C / C ++,C#和Java在post&pre increment操作符时究竟有什么区别?

这是我用VC ++ 10,Java 1.6和C#4得到的

int a = 2; int b = a++ + a++; int c = ++a + a++ + a++; +-----+------+------+----+ | C | C++ | Java | C# | +-----+-----+------+------+----+ | a | 7 | 7 | 7 | 7 | +-----+-----+------+------+----+ | b | 4 | 4 | 5 | 5 | +-----+-----+------+------+----+ | c | 15 | 15 | 16 | 16 | +-----+-----+------+------+----+ 

Java和C#从左到右评估expression式,副作用立即可见。

在C ++中,子expression式的评估顺序是不确定的,修改相同的对象两次而没有中间顺序点是未定义的行为。

我没有时间详细描述C ++,C,C#和Java之间的区别 。 我只想说,前后增量运算符的C#行为是完全指定的 (在单线程场景中;如果你想知道它的primefaces性,保证在多处理器弱存储器模型中读和写命令的观察等等,你自己做这个研究。)在C和C ++中没有完全指定; 编译器具有广泛的重要性,可以随意重新sorting副作用。 我从来没有使用Java,所以我不会冒险猜测什么是Java。

有关C#的更多信息,您应该阅读C#规范。 对于这个问题,请阅读我对这个问题的回答:

i ++和++ i有什么区别?

对于更短的采取:

C#expression式中的子expression式按照优先级和关联性进行逻辑分组,然后从左到右进行评估。 (例如,A()+ B()* C()对A(),B()和C()进行求值,乘法“加在加法之前”这一事实是不相关的;子expression式总是被求值左到右。)

如果子expression式的评估由于前或后增量子expression式而引起副作用,则在产生结果之前立即发生副作用。

在C ++中,这是未定义的行为,所以任何答案都是正确的。 有关更多详细信息,请参阅未定义的行为和顺序点 。

不知道其他语言,但我也希望这个代码也是不正确的。

编辑:
请参阅Eric Lippert关于C#的回答。 他反驳了我对C#行为的假设。

在C ++中至less有这个未定义的行为。 引用C ++标准:

在前一个和下一个序列点之间,一个标量对象应该通过评估一个expression式来最多修改其存储值。

Java内存模型确保加载和存储的顺序完成,所以它应该在任何JVM上出现(我相信)。

它看起来像C + + 具有相同的操作顺序 ,但一旦你在一条线上使用它两次,你开始跑到其他的东西(弗拉德就在那里)。 如果您尝试其他C ++编译器,您可能会发现他们提出了不同的答案。

我确定C#具有相同的操作顺序,但是我的猜测是他们有一个确保一致性的内存模型(比如Java),但是我没有太多的知识。

我喜欢这个问题,并且find了非常好的解释,但是我只是想通过它的价值来解释这个问题是如何评估的:

我只会谈论Java和C / C ++,因为我没有关于C#的知识

报表按以下方式进行评估

在java中

声明

跟踪

 int a= 2; a=2 int b= a++ + a++; a=2, a=3 here value of a=4 int c = ++a + a++ + a++; a=5, a=5, a=6 here value of a=7 

在C / C ++中

语句跟踪

 int a= 2; a=2 int b= a++ + a++; a=2, a=2 here value of a=4 int c = ++a + a++ + a++; a=5, a=5, a=5 here value of a=7 

简而言之,javaexpression式从左到右,所以在第二个“a”它将获取新的值,在c / c ++中它将首先评估整个expression式,然后增加语句的所有操作数。