(i++)+(i++)与(++i)+(++i)
当前位置:以往代写 > C/C++ 教程 >(i++)+(i++)与(++i)+(++i)
2019-06-13

(i++)+(i++)与(++i)+(++i)

(i++)+(i++)与(++i)+(++i)

副标题#e#

与在前面:++(–)有太多让人狐疑的处所,(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呈现较早的原因吧。


#p#副标题#e#

(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。功效点意外!

来看看它的字节码吧:

#p#分页标题#e#

//j=(++i)+(++i)
//5,9
 0:   iconst_3            ;常量3入栈
 1:   istore_1            ;从栈中弹出3,存入i,i=3
 2:   iinc    1, 1         ;i++, i=4
 5:   iload_1              ;将i压入栈,即4入栈
 6:   iinc    1, 1          ; 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    1, 1          ;i++,即i=4
 6:   iload_1               ;i入栈,即4入栈
 7:   iinc    1, 1           ;i++,即i=5;留意:5没有入栈,所以此时栈中的数为3和4
 10:  iadd                  ;从栈弹出两个int范例数相加,功效入栈,即7入栈
 11:  istore_2            ;从栈中弹出7,存入j,即j=7

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

    关键字:

在线提交作业