Rainyboy 发表于 2010-10-16 10:06

考古:关于“++”操作符

本帖最后由 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:22

本帖最后由 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]
查看完整版本: 考古:关于“++”操作符