未名

                                             北国风光,千里冰封,万里雪飘。 江山如此多娇,引无数英雄竞折腰。

导航

汇编下的i++与++i

Posted on 2014-08-15 00:01  未 名  阅读(2248)  评论(0编辑  收藏  举报

故事背景,一个正在c语言的家伙,问我++i 和 i++的问题,我当时因为要去上课没给他说,正好今晚有空就测试了一下如下代码:

编译环境:VS2010  语言:C++

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main(void)
 5 {
 6     int a = 1;
 7     int b = 1;
 8     int c;
 9 
10     c = a++;
11     c = ++b;
12 
13     return 0;
14 }

一、我们站在汇编的角度来说明一下问题:

可能你没学过汇编,不过没关系,我们先来科普一下汇编基本知识。(我自己也不会汇编,只是能看懂一些简单汇编代码)

-----------------------------------------------------------------

1)dword ptr  : dword -> double word 双字节   ptr ->  pointer 指针
2)mov a b : 表示将b的值赋值给a
3)add x y : 表示取x的值和y的值相加,结果再放入x中
4)另外就是cpu的8个通用寄存器 :eax, ebx, ecx, edx, esi, edi, ebp, esp
eax :是"累加器", 它是很多加法乘法指令的缺省寄存器
ecx :是"计数器", 是重复(REP)前缀指令和LOOP指令的内定计数器

-----------------------------------------------------------------

好了,下面的汇编代码我再简单解释一下,就基本差不多了。

说明:以下汇编代码解释过程中,比如:eax=1,是表示目前eax中的值为1.

 1 int a = 1;
 2 00EC136E  mov         dword ptr [a],1    //给a赋值1
 3     int b = 1;
 4 00EC1375  mov         dword ptr [b],1    //给b赋值1
 5     int c;
 6 
 7     c = a++;
 8 00EC137C  mov         eax,dword ptr [a]  //将a=1放入eax=1寄存器中
 9 00EC137F  mov         dword ptr [c],eax  //将eax=1放入c=1的地址中
10 00EC1382  mov         ecx,dword ptr [a]  //将a=1放入ecx=1寄存器中
11 00EC1385  add         ecx,1              //将ecx=1和1相加,并放入ecx=2寄存器中
12 00EC1388  mov         dword ptr [a],ecx  //将ecx=2寄存器里的值放入a=2中
13     c = ++b;
14 00EC138B  mov         eax,dword ptr [b]  //将b=1放入eax=1寄存器中
15 00EC138E  add         eax,1              //将eax=1与1相加,并放入eax=2寄存器中
16 00EC1391  mov         dword ptr [b],eax  //将eax=2寄存器里的值放入b=2中
17 00EC1394  mov         ecx,dword ptr [b]  //将b=2放入ecx=2寄存器中
18 00EC1397  mov         dword ptr [c],ecx  //将ecx=2寄存器里的值放入c=2中
19 
20     return 0;
21 00EC139A  xor         eax,eax  
22 }

从上面的一段汇编代码中我们可以很清晰的看到,汇编后:

1)c = a++;   其中c的值是1,但是a中的值却已经变化为2了。

2)c = ++b;   其中c的值是2,b的值也是2。

二、下面用C++中的 ++i 与 i++ 的重载示例来说明一下问题:

 1 /*win7_32bit,VS2010,2014年8月19日08:16:11*/
 2 #include <iostream>
 3 using namespace std;
 4 
 5 class Test
 6 {
 7 public:
 8     Test(int var) : m_var(var)
 9     {}
10     //重载i++
11     const Test operator++(int)//返回const的目的在于,使"i++ = 12"这种写法非法(注意,这里不能返回栈上的引用)
12     {
13         Test t = *this;   //保存原来的数据
14         ++m_var;
15         return t;         //返回原来的数据
16     }
17     //重载++i
18     Test& operator++()    //为了支持"++i = 10"这种写法,我们返回一个对象的引用
19     {
20         ++m_var;
21         return *this;
22     }
23     //重载输出流
24     friend ostream& operator<<(ostream& os, const Test& t);
25 private:
26     int m_var;
27 };
28 ostream& operator<<(ostream& os,const Test& t)
29 {
30     os<<t.m_var;
31     return os;
32 }
33 
34 int main(void)
35 {
36     Test a(2);
37     Test b(3);
38     cout<<a++<<endl;//result:2
39     cout<<++b<<endl;//result:4
40     ++a = 10;       //ok
41     cout<<a<<endl;  //result:10
42     //b++ = 12;  const 不能赋值,error
43 
44     return 0;
45 }

--------------------------------------------------------------

原文地址:http://www.cnblogs.com/nchar/p/3913724.html