故事背景,一个正在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. 从Go走进plan9汇编

    前言: 问:什么是plan9? 答:plan9是一个很强的操作系统,但我们只需要学习它的汇编语法. 问:为什么说golang开发者需要学习plan9汇编? 答:因为golang的开发团队和bell实验 ...

  2. Linux内核分析(一)通过汇编代码,理解程序在计算机中是如何运行的

    作者:于波 声明:原创作品转载请注明出处    来源:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 首 ...

  3. 汇编中有符号与无符号数以及CF,OF标志位的区分

    汇编中有符号与无符号数以及CF,OF标志位的区分 一. 只有一个标准! 首先需要知道,计算机对数值的存储采用补码形式存储,一来避免了+0和-0的尴尬,二来数值的加法和减法可以统一为补码的加法. 在汇编 ...

  4. linux有符号和无符号,汇编中有符号与无符号数的区分

    转载自:http://hi.baidu.com/asmsky/blog/item/7290d20076cab6da277fb5b8.html 一.只有一个标准! 在汇编语言层面,声明变量的时候,没有 ...

  5. Zynq的AMP开发注意事项之sdk_repo

    目录 前言 1.BSP工程说明 第一步:创建BSP工程,选择硬件平台.cpu核和支持的OS 第二步:BSP工程设置 (1)版本+库文件选择 (2)standalone配置 (3)drivers支持 ( ...

  6. [ARM-assembly]-全局变量/静态全局变量/初始化/未初始化变量的存放位置分析

    我们从汇编来看,各种变量在内存中的存放位置 1.使用交叉编译器将C语言转换成汇编 写一个C语言程序: static int x; static int y = 10; int z; int w = 2 ...

  7. Go interface 类型转换原理剖析

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

  8. CPU怎么认识代码的?

    # 语言这个东西? 首先说明下,我们正常使用的python.C++.C语言等等,我们自己能读得懂的语言,包括汇编语言,CPU都是不认识的,CPU 只认识一种语言,那就是 机器语言,也就是我们很多人,或 ...

  9. 解密 Go interface 的类型转换原理

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

最新文章

  1. Java 8新特性——default方法(defenece方法)介绍
  2. DM达梦数据库 - 设置忽略关键字方法,login关键字处理实例演示
  3. ffmpeg 声音参数_ffmpeg转换参数和压缩输出大小的比率
  4. python strip_Python3 strip()方法
  5. Orleans例子再进一步
  6. (七)nodejs循序渐进-模块系统(进阶篇)
  7. centos运行python程序_CentOS 7定时执行python脚本
  8. atom 快速编写html,Atom 编辑器自定义代码段(snippet)
  9. 调试器工作原理--CPU软件断点/硬件断点/单步执行标识
  10. URLEncoder.encode的默认编码问题
  11. HTML-form标签学习_015
  12. OracleXE安装完成后 http://127.0.0.1:8080/apex 总是在刷新无法打开
  13. 【洛谷P5019+P1969+P3078】道路铺设(暴力模拟/差分)
  14. Hive 安装配置及下载地址
  15. [黑苹果]黑苹果折腾记 -- 升级10.14.6 macOS Mojave
  16. php根据出生日期计算年龄函数
  17. 软件测试笔记——如何测试一个矿泉水瓶?
  18. 大连IT产业解析(2人才篇)
  19. C#,数值计算,求解微分方程的吉尔(Gear)四阶方法与源代码
  20. 论淘宝登陆滑块怎么过?selenium+python+chromedriver

热门文章

  1. mysql mvcc gap lock_为什么说 MVCC 和 Gap Lock 解决了 MySQL 的幻读问题
  2. C语言关系运算符及其表达式
  3. jieba库词频统计_运用jieba库进行词频统计
  4. python元素相邻_在python中,如何根据键(相邻组)将元素分组在...
  5. html中地图的绘制toolbars,tkinter内嵌Matplotlib系列(二)之函数曲线绘制
  6. springboot 没有找到service_Spring Boot 应用程序五种部署方式
  7. Vue结合Echarts
  8. C语言 makefile
  9. vue.js 组件基础
  10. mysql客户端工具_性能优化-理解 MySQL 体系结构(MySQL分库分表)