[i与i]一道简单的题目引发的思考.docx

  1. 1、本文档共10页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
[i与i]一道简单的题目引发的思考

 HYPERLINK /skynet/archive/2010/07/11/1775084.html 一道简单的题目引发的思考 ++i 与i++ ——Dont believe in magic !Understand what your program do ,how they do . 引言 昨晚一时兴起,我脑子就问自己下面的代码会输出什么,也不知道我脑子为什么有这个代码模型,只是模糊的有些印象: 01#include stdio.h 02#include stdlib.h  03??04int main(int argc,char** argv)  05{ 06????int i=3,j;  07????j=(i++)+(i++)+(++i); 08????printf(i = %d, j = %d\n,i,j);  09????exit(0); 10}您会怎样考虑这个问题呢?您不运行这个程序能准确地说出答案吗?我猜想肯定有大部分人不能肯定且准确地说出答案!如果您不能,这篇文章就是为你准备的,保证您看完之后豁然开朗!请细看下文???outline如下: 1、诸君的回答 我那这道题目问了几个人,他们的答案不尽相同。 1.1、A君的回答 因为i = 3,故依次i++=4,i++=5,++i=6,i最后输出为i = 6;但是由于前面两个++是后置++,最后一个++是前置++,故j = 3+4+6 = 13。 1.2、B君的回答 因为i = 3,故第一个i++后为4,第二个i++后为5,接着做i+i操作 = 5+5=10,最后与(++i)相加 = 10+6=16。 1.3、C君的回答 因为i = 3,故依次i++=4,i++=5,++i=6,i最后输出为i = 6;但是第一i、第二个i的++是后置++,先进行i+i操作,然后进行两次i++后置操作,故等价于(i)+(i) = 3+3=6,i++,i++,最后与++i=6相加等于12。 1.4、D君的回答 因为i = 3,故依次i++=4,i++=5,++i=6,i最后输出为i = 6;但是前面两个++都是后置++,故先做i+i+(++i)操作,然后才在i++,i++操作,第三个++是前置++,故等价于 i+i+(++i)=3+3+4=10,i++,i++。 到底哪个人说得对呢? 2、编译器的输出 首先让我们先来看看编译器会输出什么? 2.1、Visual Studio的输出 运行环境:Win7+VS2005 or VS2010,输出如下图所示: 2.2、GCC的输出 运行环境:Ubuntu 10.04+gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3,运行结果如下: 2.3、Visual C++的输出 运行环境:Win7+VC2010,输出和VS一样,及i = 6 j = 12 看到这里你肯定想问why? why?? why??? 3、分析 重编译器的输出结果来看貌似C君、D君的分析都是对的,这种差异跟编译器有直接的关系,因为对于这个表达式怎么编译还没有形成标准,编译器的结合方向不同,答案因此会有所不同。而且当然还包括运算符的优先级等。其实顶多算C君答对了一部分,其他几个人的回答都是错的,详情见下面的分析。 3.1、gcc编译器上的分析 (i++)+(i++)+(++i) = i+i+(++i); i++; i++;即如果表达式中含有i++,一律替换成i,然后在表达式之后进行i++操作。 这样的话上面的代码就可以很好的理解了,即3+3+4=10。 3.2、分析gcc编译之后的汇编代码 可以对gcc编译之后的执行文件进行反编译分析验证正确性。在Linux下面可以用objdump –d xxx(执行文件)命令反汇编执行文件。反编译之后可以看到如下图所示的代码: 说明:Linux下采用的是AT&T的汇编语法格式,Windows下面采用的是Intel汇编语法格式。二者的主要区别在于: 指令操作数的赋值方向是不同的 ?? Intel:第一个是目的操作数,第二个是源操作数 ?? AT&T:第一个是源操作数,第二个是目的操作数 指令前缀 ?? AT&T:寄存器前边要加上%,立即数前要加上$ ?? Intel:没有这方面的要求 内存单元操作数 ?? Intel:基地址使用[] ?? ATT:? 基地址使用() ? 比如:intel中? mov? ax,[bx] ????????????? ATT中 movl (%eax),%ebx 操作码的后缀 ???? ATT中操作码后面有一个后缀字母:“l” 32位,“w” 16位,“b” 8位 ???? Intel却使用了在操作数前面加dword ptr

文档评论(0)

haihang2017 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档