故事背景,一个正在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

从汇编来看i++与++i的更多相关文章

  1. 从汇编来看c语言之指针

    一.基础研究 将下面的程序编译连接,用debug加载: 首先执行第一条语句: 发现p=(unsigned char *)0x1000;在这里是把1000赋给一个偏移地址为01af.大小为两字节的内存空 ...

  2. 从汇编来看c语言之变量

    1.基础研究 对如图程序进行编译连接,再用debug加载. 我们在偏移地址1fa处查看main函数的内容: 执行到1fd处,发现n的偏移地址为01a6,段地址存储在ds寄存器里,为07c4. 再查看函 ...

  3. 从汇编来看c语言

    一. 学习过程 从C语言的角度提出一些问题,这些问题再从汇编的角度考虑,还真的很有意思. (1) 我们用高级语言编程时,一般不可能不用到变量,但是一定要用到变量吗?还有这些变量从汇编的角度是怎么实现的 ...

  4. MSIL Hello World

    最近由于需要,开始阅读 MSIL 方面的东西.我读的是<.NET 探秘——MSIL 权威指南>(<Expert .NET 2.0 IL Assembler>中译版).感觉没什么 ...

  5. ATPCS规则

    title: ATPCS规则 tags: ARM date: 2018-10-14 17:03:23 --- ATPCS规则 ARM指令集E004armproc.chm ATPCS介绍与使用.pdf ...

  6. (C++)i++和++i,哪个效率高一些

    在看<程序员面试笔试宝典>时,发现了这样一个问题,书中只给出了++i的效率高一些,但并没有给出具体的解释和说明. 在网上找到下面的答案: 1.从高级层面上解释 ++i 是i=i+1,表达式 ...

  7. arm下dlsym返回的符号地址居然不是偶对齐的。

    我们都知道在写汇编函数过程都会偶对齐,而gcc编译器都会将函数编译为cpu字长对齐的地址.arm指令集是固定32位指令长度,thumb指令集是固定16位指令长度, 但是运行在arm下的程序,dlsym ...

  8. Go interface 原理剖析--类型转换

    hi, 大家好,我是 haohognfan. 可能你看过的 interface 剖析的文章比较多了,这些文章基本都是从汇编角度分析类型转换或者动态转发.不过随着 Go 版本升级,对应的 Go 汇编也发 ...

  9. (七)羽夏看C语言——模板(C++)

    写在前面   由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...

随机推荐

  1. Map map=new HashMap(); 为什么是这样

    Map是接口,hashMap是Map的一种实现.接口不能被实例化. Map map=new HashMap(); 就是将map实例化成一个hashMap.这样做的好处是调用者不需要知道map具体的实现 ...

  2. bzoj2014 [Usaco2010 Feb]Chocolate Buying

    Description     贝西和其他奶牛们都喜欢巧克力,所以约翰准备买一些送给她们.奶牛巧克力专卖店里 有N种巧克力,每种巧克力的数量都是无限多的.每头奶牛只喜欢一种巧克力,调查显示, 有Ci头 ...

  3. web前端开发工程师

    web前端开发工程师 百科名片 Web前端开发工程师是一个很新的职业,在国内乃至国际上真正开始受到重视的时间不超过5年.Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征.在互联网的演化进 ...

  4. asp.net基础学习笔记

    原文地址:http://blog.csdn.net/oxoxzhu/article/details/8652530 1.概论 浏览器-服务器 B/S 浏览的      浏览器和服务器之间的交互,形成上 ...

  5. spring 定时任务(3)--配置多个定时任务

    <!-- 定义调用对象和调用对象的方法 --> <!-- 定时任务 A start --> <bean id="jobtask" class=&quo ...

  6. Python sql数据的增删改查简单操作

    1.insert import mysql.connector import os import codecs #设置数据库用户名和密码 user='root';#用户名 pwd='root';#密码 ...

  7. redi中删除所有的数据

    EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 *

  8. Python OpenGL学习(1): 环境配置及错误篇

    系统环境是:Ubuntu 14.04 个人首次接触OpenGL,学到哪就写到哪. 1.模块安装: sudo apt-get install python-openglpip install PyOpe ...

  9. Dictionary到List转换中的性能问题 转

    本文来自:http://www.cnblogs.com/353373440qq/p/3488367.html 在应用泛型中,我们经常使用Dictionary,经常会用到Dictionary到List的 ...

  10. poj 2411 Mondriaan&#39;s Dream 【dp】

    题目:id=2411" target="_blank">poj 2411 Mondriaan's Dream 题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然 ...