请解释为什么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

关于C这是未定义的行为,因为您尝试在此行的同一序列点中多次修改同一个变量:

 i = i++; 

6.5第2段中的 C99标准草案说:

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

这在Java中得到了很好的定义,它没有与C相同的序列点概念,并且Java语言规范( JLS不遗余力地确保定义了这样的操作。 JLS第15.7节说:

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

15.7.2节说:

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

注意, C没有指定评估顺序,主要是为编译器提供更好的优化选项 。 从标准草案第6.5第3段

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

更新

如果您想要讨论Java和C之间在未定义行为方面的一些哲学差异,那么Undefined行为是 Java中 的设计决策和未定义行为 。

这是C 未定义行为 。 缺乏序列点 。

在Java中, i = i++; post ++将在该步骤后增加值。 但是在将i++分配给i++的那一刻, i仍然是10所以你得到10 。 但在C中,这可能与Java不同。 如果在Java代码中使用i=++i ,则会得到11.

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

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