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

来源:互联网 发布:淘宝有哪些漫画书店铺 编辑:程序博客网 时间:2024/06/02 15:13

与在前面:++(--)有太多让人困惑的地方,(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虚拟机是一种基于栈的架构,如果它要进行两个数相加,它会先弹出两个数,再进行加法运算,再将结果入栈。

分类: 编程语言
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 没学过JAVA入职怎么办 磨砂皮擦了鞋油怎么办 磨破皮伤口有沙子怎么办 工行信用卡被风险锁定了怎么办 超重被超限站查住以后怎么办 银行卡输入密码次数超限怎么办 信用卡密码错误次数超限怎么办 农行密码错误次数超限怎么办 剪力墙偏心受拉怎么办 韵达快递寄丢了怎么办 重要快递送丢了怎么办 快递员送货丢了怎么办 买的快递丢失了怎么办 申通把件弄丢了怎么办 淘宝快递送丢了怎么办 我的快递丢了怎么办 顺丰快递丢件怎么办 韵达快递不发货怎么办 发物流丢了怎么办啊 圆通快递寄丢了怎么办 中通快递弄丢了怎么办 中通快递寄丢了怎么办 中通快递丢了怎么办 物流没保价坏了怎么办 顺丰保值快递丢了怎么办 顺丰保价件丢失怎么办 公司购买货物对方没有发票怎么办 加工货物对方不取怎么办 物流发货发错了怎么办 货车拉的货丢了怎么办 壹米滴答丢货怎么办 物流东西弄丢了怎么办 理赔款账号打错了怎么办 顺丰快递搞丢了怎么办 论文表格跨页了怎么办 网线突然没网了怎么办 室内门高门洞矮怎么办 路基填方土质含水率大怎么办 公路工程材料价格不予调差怎么办 桩基偏位60公分怎么办 定义的跨板受力筋长度不够怎么办