(编程语言中)后置++(即i++),分别通过汇编和字节码分析其在vs2012 C++和java中区别

时间:2022-10-25 17:09:46

微软的一道面试题(2014年校招)

代码:

int i=0;
i+=i>0?i++:i--;

问i等于多少?

在vs2012 C++中等于 -1,而在java中i最终等于0。


下面看看一些关于后置++的底层代码

C++代码:

int i=0;
int b=0;
b=i++;

结果:b=0 i=1

汇编代码:

int i=0;
01326D3E  mov         dword ptr [i],0   //   i<- 0
int b=0;
01326D45  mov         dword ptr [b],0   // b<- 0
b=i++;
01326D4C  mov         eax,dword ptr [i]  // eax<- i
01326D4F  mov         dword ptr [b],eax  // b<- eax
01326D52  mov         ecx,dword ptr [i]   // ecx<- i
01326D55  add         ecx,1  // ecx<- ecx+1
01326D58  mov         dword ptr [i],ecx  // i<- ecx


由汇编代码可知,vs2012 C++先将 b<- i,然后i<- i+1.

********************************************************************

C++代码:

int i=0;
int b=0;

b+=i++;

结果:b=0 i=1

汇编代码:

int i=0;
00106D3E  mov         dword ptr [i],0  //   i<- 0
int b=0;
00106D45  mov         dword ptr [b],0   // b<- 0
b+=i++;
00106D4C  mov         eax,dword ptr [b]  // eax<- b
00106D4F  add         eax,dword ptr [i]   //eax <- eax+i
00106D52  mov         dword ptr [b],eax  // b<- eax
00106D55  mov         ecx,dword ptr [i]   //  ecx<- i
00106D58  add         ecx,1      // ecx<-ecx+1
00106D5B  mov         dword ptr [i],ecx  // i<- ecx


由汇编代码可知,vs2012 C++先将 b<- b+i,然后i<- i+1.

****************************************************************************

C++代码:

int i=0;
int b=0;
b+=i>0?i++:i--;

结果:b=0 i=-1

汇编代码:

int i=0;
01166D3E  mov         dword ptr [i],0  //i<- 0
int b=0;
01166D45  mov         dword ptr [b],0  //b<- 0
b+=i>0?i++:i--;
01166D4C  cmp         dword ptr [i],0  //cmp  i , 0
01166D50  jle         main+46h (01166D66h)  //如果小于,转 main+46h (01166D66h)
01166D52  mov         eax,dword ptr [i]    //eax<- i
01166D55  mov         dword ptr [ebp-0DCh],eax  // temp <- eax (temp 临时变量)  
01166D5B  mov         ecx,dword ptr [i]   // ecx<- i
01166D5E  add         ecx,1     // ecx<- ecx+1

01166D61  mov         dword ptr [i],ecx    // i<- ecx
01166D64  jmp         main+58h (01166D78h)    //转main+58h (01166D78h)
01166D66  mov         edx,dword ptr [i]    // edx<- i
01166D69  mov         dword ptr [ebp-0DCh],edx    //temp<- edx
01166D6F  mov         eax,dword ptr [i]     //eax<- i
01166D72  sub         eax,1           //eax<- eax-1
01166D75  mov         dword ptr [i],eax    //i<- eax
01166D78  mov         ecx,dword ptr [b]    // ecx<- b
01166D7B  add         ecx,dword ptr [ebp-0DCh]   // ecx<- ecx +temp 
01166D81  mov         dword ptr [b],ecx    //b<- ecx

*****************************************************

C++代码:

int i=0;
i+=i>0?i++:i--;

结果:i=-1

汇编代码:

int i=0;
00C36D3E  mov         dword ptr [i],0   //i<- 0
i+=i>0?i++:i--;
00C36D45  cmp         dword ptr [i],0  //cmp  i , 0
00C36D49  jle         main+3Fh (0C36D5Fh)  //如果小于,转 main+3Fh (0C36D5Fh)
00C36D4B  mov         eax,dword ptr [i]    //eax<- i
00C36D4E  mov         dword ptr [ebp-0D0h],eax  // temp <- eax (temp 临时变量)  
00C36D54  mov         ecx,dword ptr [i]   // ecx<- i
00C36D57  add         ecx,1  // ecx<- ecx+1
00C36D5A  mov         dword ptr [i],ecx    // i<- ecx
00C36D5D  jmp         main+51h (0C36D71h)  //转main+51h (0C36D71h)
00C36D5F  mov         edx,dword ptr [i]   //edx<- i
00C36D62  mov         dword ptr [ebp-0D0h],edx  //temp<- edx
00C36D68  mov         eax,dword ptr [i]  //eax<- i
00C36D6B  sub         eax,1   //eax<- eax-1
00C36D6E  mov         dword ptr [i],eax   // i<- eax
00C36D71  mov         ecx,dword ptr [i]   // ecx<- i
00C36D74  add         ecx,dword ptr [ebp-0D0h]  // ecx<- ecx +temp 
00C36D7A  mov         dword ptr [i],ecx  // i<- ecx


***************************************************************

java代码:

int i=0;
i+=i>0?i++:i--;

结果:i=0

java字节码:

0: iconst_0           //stack中存入一个int常量0
1: istore_1 //把它(从栈中弹出)赋值给第一个变量,即我们的i
2: iload_1     //把i入栈
3: iload_1 //把i入栈
4: ifle          14  //如果 栈顶元素小于0,转14
7: iload_1 //把i入栈
8: iinc          1, 1 //i(变量表中的i,不是栈中的i)自加1
11: goto          18 //转18
14: iload_1 //把变量表中的i入栈
15: iinc          1, -1 //把变量表中的i自减1
18: iadd //把栈顶两个元素相加
19: istore_1 //把栈顶元素存入到 i(变量表中的i)