zoukankan      html  css  js  c++  java
  • (i++)+(i++)与(++i)+(++i)

    与在前面:++(--)有太多让人困惑的地方,(i++)+(i++)与(++i)+(++i)有什么不同?为什么不同?如果从机器的角度去理解,就会豁然开朗。

     先来看段程序:

    int main()
    {
        
    int i=3;
        
    int j=(i++)+(i++);
        
    //    int j=(++i)+(++i);
        printf("%d,%d\n",i,j);
    }

    (1)在VC 6.0下:

    对于(i++)+(i++):
    结果:i=5,j=6

    相应的汇编代码为(有详细注释):

    8B 45 FC             mov         eax,dword ptr [ebp-4]   ;i->eax
    03 45 FC             add         eax,dword ptr [ebp-4]    ;i+i=6
    89 45 F8             mov         dword ptr [ebp-8],eax    ;6->j
    8B 4D FC             mov         ecx,dword ptr [ebp
    -4]    ;i->ecx(=3)
    83 C1 01             add         ecx,1                           ;ecx=4
    89 4D FC             mov         dword ptr [ebp-4],ecx    ;4->i
    8B 
    55 FC             mov         edx,dword ptr [ebp-4]    ;i->edx
    83 C2 01             add         edx,1                           ;edx=5
    89 55 FC             mov         dword ptr [ebp-4],edx    ;5->i

     
    对于(++i)+(++i):
    结果:i=5,j=10
    相应的汇编代码为:

    8B 45 FC             mov         eax,dword ptr [ebp-4]    ;i->eax (=3)
    83 C0 01             add         eax,1                           ;eax=4
    89 45 FC             mov         dword ptr [ebp-4],eax    ;4->i
    8B 4D FC             mov         ecx,dword ptr [ebp
    -4]    ;i->ecx
    83 C1 01             add         ecx,1                           ;ecx=5
    89 4D FC             mov         dword ptr [ebp-4],ecx    ;5->i
    8B 
    55 FC             mov         edx,dword ptr [ebp-4]    ;i->edx
    03 55 FC             add         edx,dword ptr [ebp-4]    ;edx=10 ,即i+i
    89 55 F8             mov         dword ptr [ebp-8],edx    ;10->j

     
    (2)在gcc 3.2.2下:

    对于(i++)+(i++):

    结果:i=5,j=6相应的汇编代码为:

    c7 45 fc 03 00 00 00     movl    $3, -4(%ebp)        ;3->i
    8b 55 fc        movl    -4(%ebp), %edx        ;i->edx (=3)
    8b 45 fc        movl    -4(%ebp), %eax        ;i->eax    (=3)
    8d 04 10         leal    (%eax,%edx), %eax     ;i+i=6 ->eax
    89 45 f8        movl    %eax, -8(%ebp)        ;6->j
    8d 45 fc        leal    -4(%ebp), %eax        ;&i->eax
    ff 00            incl    (%eax)            ;i++ ,即i=4,注意这里为寄存器间接寻址
    8d 45 fc        leal    -4(%ebp), %eax        ;&i->eax
    ff 00            incl    (%eax)                ;i++,即i=5

     
    对于(++i)+(++i):
    结果:i=5,j=10
    相应的汇编代码为:

    movl    $3, -4(%ebp)        ;3->i
    leal    -4(%ebp), %eax        ;&i->eax
    incl    (%eax)            ;i++,即i=4
    leal    -4(%ebp), %eax        ;&i->eax
    incl    (%eax)            ;i++, i=5
    movl    -4(%ebp), %eax        ;i->eax, eax=5
    addl    -4(%ebp), %eax        ;i+i ->eax ,eax=10
    movl    %eax, -8(%ebp)        ;10->j


    可见,对于VC6.0和gcc,二者的结果一致,但是gcc 3.2.2生成的汇编代码明显比VC6.0高效、简洁。这也许是因为VC 6.0出现较早的原因吧。

    (3)如果这段代码用java实现,结果会怎样呢?

    程序:

    public class TestAdd {
        
    public static void main(String[] args) {
            
    int i=3;
            
    int j=(i++)+(i++);    //5,7
            
    //int j=(++i)+(++i);  //5,9
            System.out.println(i+","+j);
        }
    }

     对于(++i)+(++i):
    i=5,j=9。结果点意外!
    来看看它的字节码吧:

    //j=(++i)+(++i)
    //
    5,9
     
    0:   iconst_3            ;常量3入栈
     1:   istore_1            ;从栈中弹出3,存入i,i=3
     2:   iinc    11         ;i++, i=4
     5:   iload_1              ;将i压入栈,即4入栈
     6:   iinc    11          ; i++,i=5
     9:   iload_1               ;i入栈,即5入栈
     10:  iadd                  ;从栈中弹出两个int类型的数相加,结果入栈,即9入栈
     11:  istore_2            ;从栈中弹出9,存入j,即j=9

     对于(i++)+(i++):
    i=5,j=7。结果也很意外!
    也来看看它的字节码吧:

    //j=(i++)+(i++)
    //
    5,7
     
    0:   iconst_3            ;常量3入栈
     1:   istore_1            ;从栈中弹出3,存入i,i=3
     2:   iload_1               ;i入栈,即3入栈
     3:   iinc    11          ;i++,即i=4
     6:   iload_1               ;i入栈,即4入栈
     7:   iinc    11           ;i++,即i=5;注意:5没有入栈,所以此时栈中的数为3和4
     10:  iadd                  ;从栈弹出两个int类型数相加,结果入栈,即7入栈
     11:  istore_2            ;从栈中弹出7,存入j,即j=7

    Java与VC/gcc为什么会有如此的区别呢?其实原因很简单,VC/gcc生成的是本地代码,而X86处理器是基于寄存器的架构,也就是如果它要进行了两个数相加,它会先把两个数移到寄存器,再进行加法运算。而Java虚拟机是一种基于栈的架构,如果它要进行两个数相加,它会先弹出两个数,再进行加法运算,再将结果入栈。

  • 相关阅读:
    [APM] OneAPM 云监控部署与试用体验
    Elastic Stack 安装
    xBIM 综合使用案例与 ASP.NET MVC 集成(一)
    JQuery DataTables Selected Row
    力导向图Demo
    WPF ViewModelLocator
    Syncfusion SfDataGrid 导出Excel
    HTML Table to Json
    .net core 2.0 虚拟目录下载 Android Apk 等文件
    在BootStrap的modal中使用Select2
  • 原文地址:https://www.cnblogs.com/hustcat/p/1494311.html
Copyright © 2011-2022 走看看