在C
#include <stdio.h>
int main(){
int x=100;
x=x++ + x++;
printf("x : %d\n",x); // prints 202
return 0;
}
Java中的
class Demo{
public static void main(String args[]){
int x=100;
x=x++ + x++;
System.out.printf("x : %d",x); // prints 201
}
}
为什么这两种语言会打印不同的值?会发生什么'x = x ++ + x ++;'线?
答案 0 :(得分:2)
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
在Java中。
在C中,未指定组成表达式的子表达式的评估顺序,此外,x
中递增x++
的副作用可以在前一个序列之后的任何时间发生点和下一个序列点。
因此,C语言中未定义的行为是多次修改同一个对象而没有干预序列点(旧的说法),在1999年版的C语言标准中,表达(在6.5节的第2段中)为< / p>
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。此外,先前的值应该是只读的,以确定要存储的值。 70)
70)此段落呈现未定义的语句表达式,例如
i = ++i + 1; a[i++] = i; while allowing i = i + 1; a[i] = i;
该标准的当前(2011)版本用“序列点之前/之后”和“未序列”交换了“序列点”术语,6.5节的第2段现在读取
如果相对于同一标量对象的不同副作用或使用相同标量对象的值进行值计算,标量对象的副作用未被排序,则行为未定义。如果表达式的子表达式有多个允许的排序,则如果在任何排序中发生这种未测序的副作用,则行为是不确定的。 84)
(脚注84是前一个脚注70)。
在x
中递增标量对象x = x++ + x++
的两个副作用,以及在标量对象x
中存储右侧的计算值的副作用是未经测试的,因此行为未定义。
编译器可能拒绝编译包含表达式x++ + x++
的程序或完全忽略未定义的行为(或其间的任何内容)。如果它成功编译程序,则行的每个运行时行为
x = x++ + x++;
同样有效。该标准对行为施加 no 限制。