-2
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

4 回答 4

14

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

i = i++;

2节中的C99 标准草案说:6.5

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

这在 Java 中得到了很好的定义,它没有相同的序列点概念,CJava 语言规范 ( JLS ) 竭尽全力确保定义了此类操作。JLS第15.7节说:

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

和部分15.7.2说:

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

注意C没有指定求值顺序,主要是给编译器更好的优化选项。从标准部分草案6.5 第 3 段

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

更新

如果您想讨论 Java 和 C 之间关于未定义行为的一些哲学差异,您有未定义行为是设计决策Java 中的未定义行为

于 2013-08-23T12:02:51.967 回答
5

这是 中的未定义行为C缺少序列点

于 2013-08-23T12:02:21.120 回答
0

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

于 2013-08-23T12:06:34.787 回答
0

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

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

于 2013-08-23T12:57:01.173 回答