问题:
- 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;
- 004114CE mov dword ptr [i],1
- w=(++i)+(i++)+(i++)+(++i);
- 004114D5 mov eax,dword ptr [i]
- 004114D8 add eax,1
- 004114DB mov dword ptr [i],eax ;(++i)i=i+1
- 004114DE mov ecx,dword ptr [i]
- 004114E1 add ecx,1
- 004114E4 mov dword ptr [i],ecx ; (++i) i=i+1
- 004114E7 mov edx,dword ptr [i]
- 004114EA add edx,dword ptr [i]
- 004114ED add edx,dword ptr [i]
- 004114F0 add edx,dword ptr [i] ; edx=i + i + i + i
- 004114F3 mov dword ptr [w],edx ; w=edx
- 004114F6 mov eax,dword ptr [i]
- 004114F9 add eax,1
- 004114FC mov dword ptr [i],eax ; (i++)
- 004114FF mov ecx,dword ptr [i]
- 00411502 add ecx,1
- 00411505 mov dword ptr [i],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之类的,玩玩就行了,别当真。
本文内容由 Rainyboy 提供 |