Java和C中的++i + ++i + ++i有什么不同?

7
int i=2;
i = ++i + ++i + ++i;

哪个更正确?Java的结果是12还是C = 13。如果不是正确性的问题,请详细说明。

14
很奇怪,当我用C编译它时,我的编译器就像一只未定义的鸡一样跳舞。 - Craig Gidney
3
如果您确实在代码中看到了这个,我认为最好重新设计代码! - Romain Linsolas
3
为什么这些问题经常被问到?请翻译以下内容:(++x)+(++x)+(++x)的结果如何解释?请给出详细说明。注意,不要改变原来的意思或添加其他信息。 - dalle
2
@dalle - 不完全是这样,不同的编程语言会有不同的处理方式。 - Kobi
1
即使我发现++i + ++i是未定义行为,但它并不违反语言约束,这让我有些惊讶。更重要的是,如果调用者为p和q传入不同的值,则int incboth(int *p, int *q) { return ++*p + ++*q; }是可以的,如果使用相同的指针值两次调用则不行。显然编译器无法帮助您解决这个问题(尽管C99的restrict至少表明了意图),这就是为什么序列点规则不能完全表示为语言约束的原因。 - Steve Jessop
显示剩余12条评论
4个回答

29

Java保证(§15.7.1)表达式将从左到右进行求值,得出12。具体来说,+++有更高的优先级。所以它首先绑定这些运算符,然后从左到右关联加法操作。

i = (((++i) + (++i)) + (++i));

根据§15.7.1,左操作数先被求值,而§15.7.2规定在运算前两个操作数都会被求值。因此它的求值顺序如下:

i = (((++i) + (++i)) + (++i));
i = ((3 + (++i)) + (++i)); // i = 3;
i = ((3 + 4) + (++i)); // i = 4;
i = (7 + (++i)); // i = 4;
i = (7 + 5); // i = 5;
i = 12;

在C语言中,如果没有序列点,就连续两次修改变量是未定义的行为。


一个小问题 - 这里真的需要从左到右吗?在这个例子中,另一种顺序会给出不同的结果吗?我想这更与像 i = (i*=2) + (i*=3) + (i*=4); 这样的语句有关,其中顺序很重要。 - Kobi
@Kobi,不是真的,但我希望解释简单的情况可以帮助人们逐步处理更复杂的情况。 - Matthew Flaschen
4
将其改为++i - ++i - ++i,并且从左到右的顺序变得非常重要。 - PaulMcG
еңЁ((3 + 4) + (++i))д№ӢеҗҺзҡ„жӯҘйӘӨдёҚеә”иҜҘжҳҜ((3 + 4) + 5)еҗ—пјҹеӣ дёә++жҜ”+зҡ„дјҳе…Ҳзә§жӣҙй«ҳгҖӮ - configurator
@config,重要的是要区分优先级和计算顺序。优先级基本上确定了模拟括号的位置;计算顺序是实际计算的顺序。计算顺序在§15.7中有所说明。由于§15.7.1,左操作数(3 + 4)必须在右操作数(++i)(外部+的)之前进行评估。 - Matthew Flaschen

18

1
谢谢,我对“序列点错误”这个术语有了更深刻的理解。 - Manny
16
Java中定义得很清晰。 - Matthew Flaschen

7

Java的结果对我来说是有意义的,因为运算符给出了你所期望的结果,但是没有任何严肃的程序应该包含这样的语句。

编辑:我很高兴这个简短的回答成为了今晚我得分最高的答案(与我发布的其他答案相比,其中一些还包括了代码示例)。这就是生活。


5

在C语言中,这是未定义行为。没有正确的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接