今天在CSDN上面看到一个帖子
提出了这样一个问题
int i=10;
i+=i++;
i最后是多少呢?
呵呵。。。那个作者用C#和VC.NET分别试验结果是20和21
我还用java做了试验,结果也是20。。。
为什么C#和java会是20呢?
我用C#写了程序,反编译结果如下:
19: int i=10;
00000000 55 push ebp
00000001 8B EC mov ebp,esp
00000003 83 EC 08 sub esp,8
00000006 57 push edi
00000007 56 push esi
00000008 33 C0 xor eax,eax
0000000a 89 45 F8 mov dword ptr [ebp-8],eax
0000000d 89 4D FC mov dword ptr [ebp-4],ecx
00000010 C7 45 F8 0A 00 00 00 mov dword ptr [ebp-8],0Ah
20: i+=i++;
00000017 8B 7D F8 mov edi,dword ptr [ebp-8]
0000001a 8B 75 F8 mov esi,dword ptr [ebp-8]
0000001d FF 45 F8 inc dword ptr [ebp-8]
00000020 03 FE add edi,esi
00000022 89 7D F8 mov dword ptr [ebp-8],edi
从这里我们可以看到,C#里面是先将i和要加上的i放到了寄存器中,然后将原来的i加1,接着做那个i+=i的处理,然后将结果20写回原来的地址,所以最后的结果为20
21: Console.WriteLine(i.ToString());
00000025 8D 4D F8 lea ecx,[ebp-8]
00000028 E8 DB AD BD FF call FFBDAE08
0000002d 8B F0 mov esi,eax
0000002f 8B CE mov ecx,esi
00000031 FF 15 CC 4D 83 03 call dword ptr ds:[03834DCCh]
因为机器上面没有VC.NET,我用VC 6写了一个程序,反编译如下:
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
8: int i=10;
00401028 mov dword ptr [ebp-4],0Ah
9: i+=i++;
0040102F mov eax,dword ptr [ebp-4]
00401032 add eax,dword ptr [ebp-4]
00401035 mov dword ptr [ebp-4],eax
00401038 mov ecx,dword ptr [ebp-4]
0040103B add ecx,1
0040103E mov dword ptr [ebp-4],ecx
从这里很清楚的看到,这里是先做了i+=i的操作,然后再将i加1,所以结果就是21了
10:
11: printf("%d",i);
00401041 mov edx,dword ptr [ebp-4]
00401044 push edx
00401045 push offset string "%d" (0042001c)
0040104A call printf (00401080)
0040104F add esp,8
12: return 0;
00401052 xor eax,eax
提出了这样一个问题
int i=10;
i+=i++;
i最后是多少呢?
呵呵。。。那个作者用C#和VC.NET分别试验结果是20和21
我还用java做了试验,结果也是20。。。
为什么C#和java会是20呢?
我用C#写了程序,反编译结果如下:
19: int i=10;
00000000 55 push ebp
00000001 8B EC mov ebp,esp
00000003 83 EC 08 sub esp,8
00000006 57 push edi
00000007 56 push esi
00000008 33 C0 xor eax,eax
0000000a 89 45 F8 mov dword ptr [ebp-8],eax
0000000d 89 4D FC mov dword ptr [ebp-4],ecx
00000010 C7 45 F8 0A 00 00 00 mov dword ptr [ebp-8],0Ah
20: i+=i++;
00000017 8B 7D F8 mov edi,dword ptr [ebp-8]
0000001a 8B 75 F8 mov esi,dword ptr [ebp-8]
0000001d FF 45 F8 inc dword ptr [ebp-8]
00000020 03 FE add edi,esi
00000022 89 7D F8 mov dword ptr [ebp-8],edi
从这里我们可以看到,C#里面是先将i和要加上的i放到了寄存器中,然后将原来的i加1,接着做那个i+=i的处理,然后将结果20写回原来的地址,所以最后的结果为20
21: Console.WriteLine(i.ToString());
00000025 8D 4D F8 lea ecx,[ebp-8]
00000028 E8 DB AD BD FF call FFBDAE08
0000002d 8B F0 mov esi,eax
0000002f 8B CE mov ecx,esi
00000031 FF 15 CC 4D 83 03 call dword ptr ds:[03834DCCh]
因为机器上面没有VC.NET,我用VC 6写了一个程序,反编译如下:
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
8: int i=10;
00401028 mov dword ptr [ebp-4],0Ah
9: i+=i++;
0040102F mov eax,dword ptr [ebp-4]
00401032 add eax,dword ptr [ebp-4]
00401035 mov dword ptr [ebp-4],eax
00401038 mov ecx,dword ptr [ebp-4]
0040103B add ecx,1
0040103E mov dword ptr [ebp-4],ecx
从这里很清楚的看到,这里是先做了i+=i的操作,然后再将i加1,所以结果就是21了
10:
11: printf("%d",i);
00401041 mov edx,dword ptr [ebp-4]
00401044 push edx
00401045 push offset string "%d" (0042001c)
0040104A call printf (00401080)
0040104F add esp,8
12: return 0;
00401052 xor eax,eax