考古:关于“++”操作符
本帖最后由 Rainyboy 于 2010-10-16 10:07 编辑问题:
int w,i;
i=1;
w=(++i)+(i++)+(i++)+(++i); i和w执行完上述语句后的值各是多少
这个问题在《C陷阱和缺陷》和《C++ Primer》里面已经说得足够明白:不同的编译器将得到不同的结果,今日有幸考古,所记录如下,编译环境:Visual Studio 8.0
先说结果:i=5,w=12
反汇编如下:
int w,i;
i=1;
004114CEmov dword ptr ,1
w=(++i)+(i++)+(i++)+(++i);
004114D5mov eax,dword ptr
004114D8add eax,1
004114DBmov dword ptr ,eax;(++i)i=i+1
004114DEmov ecx,dword ptr
004114E1add ecx,1
004114E4mov dword ptr ,ecx; (++i) i=i+1
004114E7mov edx,dword ptr
004114EAadd edx,dword ptr
004114EDadd edx,dword ptr
004114F0add edx,dword ptr ; edx=i + i + i + i
004114F3mov dword ptr ,edx; w=edx
004114F6mov eax,dword ptr
004114F9add eax,1
004114FCmov dword ptr ,eax; (i++)
004114FFmov ecx,dword ptr
00411502add ecx,1
00411505mov dword ptr ,ecx; (i++) 按照返汇编的结果,i的值在同一个时间内只有一个,dword ptr 的值在每一次操作之后都会改变,因此导致了这样的流程:
1,计算所有的(++i),即i自增
2,所有的(i++)忽略,即i不自增
3,按照上述两步之后的i值带入所有的(i++)和(++i)之中
Temp:赋值给w
4,待整个语句执行完毕之后,再执行所有的(i++)的影响。
怎么说呢,按照编译原理的表达式求值规则,应该是用到堆栈,一个栈用来存放操作数,另一个栈用来存放操作符,局部的表达式求值后继续压入栈内。
也许是为了提高效率之类的理由吧,Visual Studio 8.0没有这样做,才导致了这么出人意外的结果。
这也许也就是为什么1000本C教材就有1001本告诫读者:i++,++i之类的,玩玩就行了,别当真。
本帖最后由 wqsong 于 2010-10-18 01:23 编辑
调侃一下。。。呵呵,其实按找运算符的优先级还是有迹可循的,上面的代码应该写成下面这样。。。但的确,编译器实现都不同,或许是加的多了,寄存器不够用了。。。;@P;@P:lol;++a,eax保存当时的值
mov eax,dword ptr
add eax,1
mov dword ptr ,eax
;a++,ebx保存当时的值
mov ebx,dword ptr
mov ebp, ebx ;借用一下ebp
add ebx,1
mov dword ptr ,ebx
mov ebx, ebp
;a++,ecx保存当时的值
mov ecx,dword ptr
mov ebp, ebx ;;借用一下ebp
add ecx,1
mov dword ptr ,ecx
mov ebx, ebp
;++a,eax保存当时的值
mov edx,dword ptr
add edx,1
mov dword ptr ,edx
;
add edx, eax
add edx, ebx
add edx, edx
mov dword ptr ,edx
页:
[1]