在一些面试题中,很多面试官会故意出一些很刁钻的题来考面试者。当面对这种问题时,不要慌,第一个出口的答案必须是,虽然这些看起来技巧性很高的代码对我们理解语言与编译器的本质很有用途,但是实际开发过程中应该尽量避免高技巧性的写法,尽量做到通俗易懂,下面以我个人的见解对这道题的分析是:
譬如下面这些题:
1、请问:
#include
using namespace std;
int main()
{
int i = 10;
i = (i++) + (i++) + (++i);
cout << i <
输出的i的结果会是多少?
答案是:
好,下面我们来进行简单的分析(如果你实在看不懂下边的汇编源码,万不得已可以记住这个定律)
无论如何i++总是在一条语句中直接取i进行运算,等语句执行完再执行自加;就譬如j=i++一样可以拆成j=i和i=i+1;
我们总是会把i代入给j等到语句结束后后面再执行i=i+1;
而在一道表达式里++i总是在任何一个执行到他的语句的前一时刻执行,我们讲得生动点就是,你先在这稍等一下,让我++i执行完了再来告诉你继续执行
好了,有了上面2个分析点,我们来分析一下i = (i++) + (i++) + (++i);
此时是这样的情况 “ i = i + i ...你得稍等一下我++i执行完再来告诉你 "此时执行i=i+1,执行完此时i就是11;但是由于之前i已经是10了,所以等号右边前2个i是10,第3个i是11;所以i = 10 + 10 + 11 = 31 ,有同学就说,咦,不对啊,答案是33,哈哈,其实你是忘了我们的i++,要等这个赋值语句执行完了,再执行2次自加,而此时i已经是31了,自加2次自然就是33了。
有兴趣的朋友可以用上面的方法研究一下i = (++i)+(i++) + (i++) ;
j=++i与j=i++的汇编源码:
我们知道,j=++i是可以看成由2条语句组成的:
1 i = i + 1;
2 j = i;
同样,j = i++也是可以看成:
1 j = i;
2 i = i + 1;
那么,在汇编里的实现会是怎样呢?
下面是我在vc6.0中做测试时所copy下来的汇编源码。
j = i++;
00401276 mov eax,dword ptr [ebp-4]
00401279 mov dword ptr [ebp-8],eax
0040127C mov ecx,dword ptr [ebp-4]
0040127F add ecx,1
00401282 mov dword ptr [ebp-4],ecx
j = ++i;
00401276 mov eax,dword ptr [ebp-4]
00401279 add eax,1
0040127C mov dword ptr [ebp-4],eax
0040127F mov ecx,dword ptr [ebp-4]
00401282 mov dword ptr [ebp-8],ecx
部分解释:
ptr[ebp-4]相当于我们题中i所在的内存位置
ptr[ebp-8]相当于我们题中j所在的内存位置
在这里就只解释j=++i的汇编。
00401276 mov eax,dword ptr [ebp-4]
这个的意思是,将i从内存中取出值存到eax这个寄存器中
00401279 add eax,1
这个的意思是, 对寄存器eax中的值实行add 1 的操作
0040127C mov dword ptr [ebp-4],eax
这个是将eax中的值存回i所对应的内存中的地址(即改变内存中i的值)
0040127F mov ecx,dword ptr [ebp-4]
这个是将i对应的内存中的值取到ecx这个寄存器中
00401282 mov dword ptr [ebp-8],ecx
这个是将ecx这个寄存器中的值赋值到j所指向的内存的空间(即改变内存中j的值)
至此,j = ++i语句执行完成。
一开始我也不懂,为什么汇编中要这么复杂去实现。后面理解了计算机在运算时的原理时,
才知道计算机在做运算的时候,是得靠寄存器间接操作的,所以++i就得拆成3条汇编去执行(!!这个跟多线程安全密切相关!!)
本文由Cout_Sev 撰写。
若有错误欢迎指正
转载请注明出处:http://blog.csdn.net/cout_sev/
谢谢合作!
部分解释:
ptr[ebp-4]相当于我们题中i所在的 内存 位置ptr[ebp-8]相当于我们题中j所在的内存位置
部分解释:
ptr[ebp-4]相当于我们题中i所在的内存位置
ptr[ebp-8]相当于我们题中j所在的内存位置