int i = 0;
i = i++;
System.out.println(i); // ?
最终结果是什么? JAVA 结果为 0, C/C++结果为 1.
JAVA
public classMain {
public static voidmain(String[] args) {
Integer i =0;
i = i++;
System.out.println(i);
}
}
http://wangwengcn.iteye.com/blog/1622195
Java虚拟机栈(JVM Stack)描述的是Java方法执行的内存模型,而JVM内存模型是基于“栈帧”的,每个栈帧中都有局部变量表和操作数栈(还有动态链接、return address等).
局部变量表:变量值存储空间.存放方法参数和方法内部定义的局部变量.
操作数栈:虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。
如下图是JAVAP转换成的JVM指令.
JVM指令详解: http://blog.csdn.net/hudashi/article/details/7062675
根据上面的JVM指令,局部变量表 index_1,index_2,index_3被使用到. 而index_1是实际i的值.
6:保存原始的i值到index_2
之后没有使用index_2
19:重新使用index_2的值,并覆盖了index_1的值.
在我看来,可能是JAVA的一个bug.
JVM里面有两个存储区,一个是暂存区(是一个堆栈,以下称为堆栈),另一个是变量区。
JVM会这样运行这条语句,
步骤1: 把 i 值(其值是0)拷贝到临时变量区。
步骤2: i 值加1,这时候 i 的值是1。
步骤3: 返回临时变量区的值,注意这个值是0,没修改过。
步骤4: 返回值赋值给 i,此时 i 值被重置成0。
C/C++中没有另外设置一个临时变量或是临时空间来保存 i,所有操作都是在一个内存空间中完成的,所以在C/C++中是1。
C/C++
http://blog.csdn.net/oldmanzhao/article/details/43851877
int c = ++i;
012D1384 mov eax,dword ptr [i]
012D1387 add eax,1
012D138A mov dword ptr [i],eax
012D138D mov ecx,dword ptr [i]
012D1390 mov dword ptr [c],ecx
可以看到这个操作在完成了前三部之后做了两个mov把最终的i值放到了c中
int b = i++;
012D1375 mov eax,dword ptr [i]
012D1378 mov dword ptr [b],eax
012D137B mov ecx,dword ptr [i]
012D137E add ecx,1
012D1381 mov dword ptr [i],ecx
结果稍有不同,在把i的值mov到eax之后又立即把eax放到了b中,随后的三步保持与之前一致只不过寄存器换成了ecx,正好符合i++的特性.
那么,JVM指令与汇编命令之间的关系与映射是怎样的?
不知道为什么,在mac上,使用visual code和sublime跑C++的的这段程序,结果却是0. 在Windows上,这段程序结果却是1.
可能是编译器不同吧?
网友评论