Java 和 C 是不同的语言,因此并非所有在两者中都在语法上有效的结构(有很多,因为 Java 的语法建立在 C 之上)在两者中都必须具有相同的含义。
构造
int x=100;
x=x++ + x++;
是一个例子。在 Java 中,表达式的计算顺序被指定为从左到右,并且递增的副作用x
必须x++
在计算表达式的下一部分之前发生。因此,上面的代码 - 除了临时变量 - 相当于
int x = 100;
int left = x++; // sets left to x's value (100) and increments x, so x is now 101
int right = x++; // sets right to x's current value (101) and increments x, so x is now 102
x = left + right; // 100 + 101 = 201
在爪哇。
在 C 中,没有指定组成表达式的子表达式的求值顺序,此外,递增的副作用x
可以x++
在前一个序列点和下一个序列点之后的任何时间发生。
因此,在 C 语言标准的 1999 版本中,多次修改同一个对象而不干预序列点(旧用语)是 C 中未定义的行为,表示为(在第 6.5 节的第 2 段中)
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。70)
70)本段呈现未定义的语句表达式,例如
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
当前(2011)版本的标准将“sequence point”术语替换为“sequenced before/after”和“unsequenced”,第 6.5 节的第 2 段现在为
如果标量对象的副作用相对于同一标量对象的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。如果表达式的子表达式有多个允许的排序,则如果在任何排序中出现这种未排序的副作用,则行为未定义。84)
(脚注 84 是之前的脚注 70)。
x
在 中增加标量对象的两个副作用x = x++ + x++
以及将右侧的计算值存储在标量对象中的副作用x
是无序的,因此行为是未定义的。
编译器可能拒绝编译包含表达式的程序x++ + x++
或完全忽略未定义的行为(或介于两者之间的任何行为)。如果它成功编译程序,则该行的每个运行时行为
x = x++ + x++;
同样有效。该标准对行为没有任何限制。