(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     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虚拟机是一种基于栈的架构,如果它要进行两个数相加,它会先弹出两个数,再进行加法运算,再将结果入栈。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在for循环中,i++++i是两种不同的自增操作。i++表示先使用i的值,然后再将i加1;而++i表示先将i加1,然后再使用i的值。\[1\]在Java中,i++语句需要一个临时变量来存储返回自增前的值,而++i则不需要。这导致使用i++时系统需要先申请一段内存空间,然后将值存入其中,最后再释放。因此,在循环次数较多的情况下,使用++i会比i++更高效。\[2\]举个例子,如果我们有一个for循环,其中i的初始值为0,每次循环结束后i自增1,那么使用i++时,循环中的操作会先使用i的值,然后再将i加1;而使用++i时,循环中的操作会先将i加1,然后再使用i的值。\[3\] #### 引用[.reference_title] - *1* *3* [C++中for循环中++i和i++](https://blog.csdn.net/qq_41006629/article/details/123983985)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [for循环中 i++++i 区别](https://blog.csdn.net/fromVillageCoolBoy/article/details/128750056)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值