请解释为什么Java和C为此代码提供不同的答案

时间:2013-08-23 11:59:54

标签: java c

public class Test
{
    public static void main(String[] args) {
        int i = 10;
        i = i++;
        System.out.println("value of i is : " + i);
    }
}

输出为:10

当我在C中执行类似的代码时,输​​出为11

4 个答案:

答案 0 :(得分:14)

关于C这是undefined behavior,因为您尝试在此行的同一sequence point内多次修改同一个变量:

i = i++;

6.5 第2段中的draft C99 standard说:

  

在上一个和下一个序列点之间,对象应具有其存储值   通过表达式的评估,最多修改一次。此外,先前的值   应该只读以确定要存储的值

这在Java中得到了很好的定义,它没有C所做的相同的序列点概念,并且Java语言规范( JLS )不再适用确保定义此类操作。 JLS的15.7部分说:

  

在评估右侧操作数的任何部分之前,二元运算符的左侧操作数似乎已完全评估。例如,如果左侧操作数包含对a的赋值变量和右侧操作数包含对同一变量的引用,然后引用生成的值将反映赋值首先发生的事实。 [...]

和第15.7.2部分说:

  

Java编程语言还保证在执行操作本身的任何部分之前,运算符的每个操作数(条件运算符&&,||和?:) 除了完全评估之外。

请注意,C未指定评估顺序,主要是为了给编译器better options for optimization。来自标准草案部分6.5 第3段

  

运算符和操作数的分组由语法表示.74)除非另有说明   稍后(对于函数调用(),&&,||,?:和逗号运算符),子表达式的评估顺序和副作用发生的顺序都是未指定的。

更新

如果您想讨论Java和C之间在未定义行为方面的一些哲学差异,那么您需要Undefined behavior is a design decisionUndefined behaviour in Java

答案 1 :(得分:5)

这是C中的Undefined behaviour。缺乏sequence point

答案 2 :(得分:0)

在Java中,i = i++; post ++将在该步骤后增加值。但是,在将i++分配给i时,i仍为10,因此您获得了10。但在C中,这可能与Java不同。如果您在i=++i代码中使用Java,则会获得11.

答案 3 :(得分:0)

Java和C是具有不同规则的不同语言。在C中,评估表达式和应用副作用的确切顺序是未指定;对于i = i++这样的表达式,无法保证在作业发生之前应用++运算符的副作用。结果将根据平台,优化设置,甚至周围的代码而有所不同。行为未定义;编译器可以按照它认为合适的方式处理这种情况,包括产生意外结果。

Java,OTOH确实指定了严格的评估顺序,并且立即应用了副作用,因此表达式定义明确。