Pre & post increment operator behavior in C, C++, Java, & C#
免责声明:这不是一个真实的例子。这只是这些语言如何工作的一个理论问题。
当涉及到邮政和预增值运营商时,C/C++、C语言和Java的区别究竟是什么?
这就是我在VC++ 10、Java 1.6和C 4中所得到的。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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语言评估从左到右的表达式,并且副作用是立即可见的。
在C++中,未指定子表达式的评估顺序,并且在没有中间序列点的情况下修改同一对象两次是未定义的行为。
我没有时间详细描述C++、C、C和Java之间的区别。我只想说,增量前后操作符的c行为是完全指定的(在单线程场景中;如果你想知道它的原子性,保证在多处理器弱内存模型中观察读写顺序等等,你可以自己做这项研究。)它在c和an中没有完全指定。一个编译器有宽大的毅力去做任何事情,并重新排序副作用。我从来没有使用过Java,所以我不会冒险猜测Java是做什么的。
有关C的更多信息,请阅读C规范。简单来说,请阅读我对这个问题的回答:
我++和我的区别是什么?
对于更短的拍摄时间:
C表达式中的子表达式按优先级和关联性进行逻辑分组,然后从左到右进行计算,不管如何。(例如,a()+b()*c()计算a(),然后b(),然后c()。乘法"先于"加法的事实是不相关的;子表达式总是从左到右进行计算。)
如果子表达式的计算由于增量前或增量后的子表达式而导致副作用,则副作用会在生成结果之前立即发生。
在C++中至少有这种未定义的行为。引用C++标准:
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
在C++中,这是未定义的行为,所以任何答案都是正确的。有关详细信息,请参见未定义的行为和序列点。
不确定其他语言,但我希望这里的代码也不正确。
编辑:参见埃里克·利珀特关于C的回答。他反驳了我对C的行为的假设。
我喜欢这个问题,并找到了很好的解释,但我只想用它的价值来解释这个问题,它是如何被评价的:
我只会谈论Java和C/C++,因为我对C语言一无所知。
语句的评估方法如下
在爪哇
声明124124124124124124124124124124124124124124124124124124124124124124124124124124124\\124124__trace
1 2 3 4 5 6 7 8 | 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++中
语句跟踪
1 2 3 4 5 6 7 8 | 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 |
简而言之,Java表达式左到右,因此在第二"A"中它将获得新的值,而在C/C++中,它将首先评估整个表达式,然后递增语句的所有操作数。
Java内存模型确保了加载和存储完成的顺序,所以它应该在任何JVM上都是相同的(我相信)。
看起来C++具有相同的操作顺序,但是一旦你在一行上使用了两次,你就开始运行其他的东西(弗拉德就在那里)。如果你尝试其他C++编译器,你可能会发现他们有不同的答案。
我确信C的操作顺序相同,但我猜想他们有一个内存模型(比如Java)来确保一致性,但是我这里没有很多知识。