今天计算技术基础课上有同学提出一个问题,C++里,a=0,(++a)+(++a)+(++a)为什么会等于7?
当时想可能就是自己想的,但不确定,回来后把程序反汇编一下,发现和自己想的是一样的。对此问题的解释如下:
C++程序为:
int main()
{
int a = 0;
int b = 0;
b = (++a) + (++a) + (++a);
return 0;
}
反汇编以后的主要语句代码如下:
[01]:00401028 C745FC00000000 mov [ebp-04], 00000000
[02]:0040102F C745F800000000 mov [ebp-08], 00000000
[03]:00401036 8B45FC mov eax, dword ptr [ebp-04]
[04]:00401039 83C001 add eax, 00000001
[05]:0040103C 8945FC mov dword ptr [ebp-04], eax
[06]:0040103F 8B4DFC mov ecx, dword ptr [ebp-04]
[07]:00401042 83C101 add ecx, 00000001
[08]:00401045 894DFC mov dword ptr [ebp-04], ecx
[09]:00401048 8B55FC mov edx, dword ptr [ebp-04]
[10]:0040104B 0355FC add edx, dword ptr [ebp-04]
[11]:0040104E 8B45FC mov eax, dword ptr [ebp-04]
[12]:00401051 83C001 add eax, 00000001
[13]:00401054 8945FC mov dword ptr [ebp-04], eax
[14]:00401057 0355FC add edx, dword ptr [ebp-04]
[15]:0040105A 8955F8 mov dword ptr [ebp-08], edx
下面是对每句指令的分析(注:+是右运算符,是从左向右计算):
[01]:将0赋给a,a所在的地址为[ebp-04],int型变量在内存中占四个字节
[02]:将0赋给b,b的地址为[ebp-08]
[03]:把a放到寄存器eax中,eax中值为0,dword ptr代表以双字(4字节)放入
[04]:寄存器eax中数值+1,计算结果是:++0=1,应该是计算第一个括号里的++a
[05]:把寄存器计算结果放入内存,a所在的地址。——此时a即地址[ebp-04]中的值为1
[06]:把a放到寄存器ecx中,ecx中值为1
[07]:寄存器ecx中数值+1,计算结果是:++1=2,应该是计算中间括号里的++a
[08]:把寄存器计算结果放入内存,a所在的地址。——此时a即地址[ebp-04]中的值为2
[09]:把a放到寄存器edx中,edx中值为2
[10]:把edx寄存器中的值加上a的值,实际是为了计算(++a)+(++a),计算结果是:edx:2+2=4
[11]:把a放到寄存器eax中,eax中值为2
[12]:寄存器eax中数值+1,计算结果是:++2=3,应该是计算最后一个括号里的++a
[13]:把寄存器计算结果放入内存,a所在的地址。——此时a即地址[ebp-04]中的值为3
[14]:把a的值加到edx上,计算第一个括号外面的加号,得:edx:3+4=7
[15]:把edx中的计算结果放入b所在的地址,[ebp-08]
结论:
由此可见,之所以会产生a=0,(++a)+(++a)+(+ +a)=7的情况,是由语句的执行顺序决定的,语句执行时候先计算“+”号两边的值,然后再把它们的计算结果相加。当两边都是++a时,两次++先执行,再执行+,这样就造成了“+”号两边的值是一样的,2+2=4,其他的依次类推。
Copyright © 2005-2006 Solrex Yang. All rights reserved.
想问一下,你用的是哪种反汇编工具?
很多种反汇编工具可供选择的,我这个例子是在 Windows 下完成的
大概用的是 Win32 Debugger 吧,记不太清楚了
在solaris 环境下用 g++编译得到的结果是 6,而不是7
我得到的值是9啊?解释不通啊?
刚看了你补充的那篇,明白了,呵呵,博主不用回复了,^_^