美文网首页
JAVA i = i++;

JAVA i = i++;

作者: iFavorite | 来源:发表于2017-09-29 16:39 被阅读51次

    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.

    可能是编译器不同吧?

    相关文章

      网友评论

          本文标题:JAVA i = i++;

          本文链接:https://www.haomeiwen.com/subject/wegiextx.html