Chinaunix首页 | 论坛 | 博客
  • 博客访问: 662307
  • 博文数量: 137
  • 博客积分: 7000
  • 博客等级: 少将
  • 技术积分: 1335
  • 用 户 组: 普通用户
  • 注册时间: 2005-11-23 15:18
文章分类

全部博文(137)

文章存档

2010年(2)

2009年(2)

2008年(2)

2007年(30)

2006年(99)

2005年(2)

我的朋友

分类: C/C++

2005-11-25 16:03:15

下面关于自增运算符处理的细节问题,问题如下:

int i = 0;
i = (i++) + (++i);
i = ?
那天小帆同学在群里问起,我图方便,顺手写了个脚本如下:

<html>
<script>
var i = 0;
i = (i++)+(++i);
alert(i);
</script>
</html>


执行该脚本计算得i=2;不想小帆却告诉我i=3!?并给出VC的执行过程:
9: int i=0;
0040B488 mov dword ptr [ebp-4],0
10: i=(i++)+(++i);
0040B48F mov eax,dword ptr [ebp-4] (++i开始)
0040B492 add eax,1 (++i)
0040B495 mov dword ptr [ebp-4],eax (++i结束)
0040B498 mov ecx,dword ptr [ebp-4]
0040B49B add ecx,dword ptr [ebp-4] (i+i,i已执行++i操作,这里是1+1)
0040B49E mov dword ptr [ebp-4],ecx (i=2的赋值操作)
0040B4A1 mov edx,dword ptr [ebp-4] (i++开始)
0040B4A4 add edx,1 (i++)
0040B4A7 mov dword ptr [ebp-4],edx (i++结束)
如果您能看懂以上代码就知道为什么i=3而不等于2了,i的值在最后进行处理,改变了最后的结果。
如果改成如下过程:
int i = 0;
j = (i++) + (++i);
j = ?
汇编码如下:
17: j=(i++)+(++i);
0040B7D9 mov ecx,dword ptr [ebp-4]
0040B7DC add ecx,1
0040B7DF mov dword ptr [ebp-4],ecx
0040B7E2 mov edx,dword ptr [ebp-4]
0040B7E5 add edx,dword ptr [ebp-4]
0040B7E8 mov dword ptr [ebp-8],edx (j=2赋值,注意,结果被放在了高8位)
0040B7EB mov eax,dword ptr [ebp-4] (i++仍然放在最后执行)
0040B7EE add eax,1
0040B7F1 mov dword ptr [ebp-4],eax
很显然,j=2!
通过对比我们应该知道:在表达式的执行过程中,i++操作是放在最后执行的,甚至在"="赋值操作之后。
真相大白,hoho,搞清楚了个问题,值得高兴。
如果再不信,去试试:
i = (i++) + (i++),i是不是等于2? (0+0,接着i两次自加)
j = (i++) + (i++),j是不是等于0? (i没自加前把值赋给了j)
就知道了:)
至于在javascript里执行结果为什么是3?仿佛我对js没什么兴趣,有兴趣的同学去研究吧。
-------------------------------------------------------------------------
Linux版本:
源代码:

#include <stdio.h>

int main()
{
  int i = 1, j = 1, k;

  i = (i++) + (++i);
  printf("i=%d \n", i);

  k = (j++) + (++j);
  printf("j=%d, k=%d\n", j, k);
}

执行结果:

i=5
j=3, k=4


关键的汇编码片段:

 movl $0x1,0xfffffff0(%ebp)
 movl $0x1,0xfffffff4(%ebp)
 addl $0x1,0xfffffff0(%ebp)
 mov 0xfffffff0(%ebp),%eax
 add %eax,0xfffffff0(%ebp)
 addl $0x1,0xfffffff0(%ebp)
 mov 0xfffffff0(%ebp),%eax
 mov %eax,0x4(%esp)
 movl $0x8048500,(%esp)
 call 80482f8 <printf@plt>
 addl $0x1,0xfffffff4(%ebp)
 mov 0xfffffff4(%ebp),%eax
 add 0xfffffff4(%ebp),%eax
 mov %eax,0xfffffff8(%ebp)
 addl $0x1,0xfffffff4(%ebp)
 mov 0xfffffff8(%ebp),%eax
 mov %eax,0x8(%esp)
 mov 0xfffffff4(%ebp),%eax
 mov %eax,0x4(%esp)
 movl $0x8048507,(%esp)
 call 80482f8 <printf@plt>


明白了以后这就不难解释为什么i=1,执行(++i)+(++i)之后为什么i=6了。
阅读(1958) | 评论(2) | 转发(0) |
0

上一篇:8088 汇编速查手册

下一篇:Tips for Vim

给主人留下些什么吧!~~