i++与++i的汇编级实现
最近见到一道试题:
int x=20; int y=35;
x = y++ + x++; y = ++y + ++x;
cout << x << endl; cout << y << endl; |
问x、y最后都是多少。说实话,写了十年的程序了,我也没写出这样的代码来。可见这样的代码只有技术上的意义,实践中一般是用不到的。正确答案是57和94。我先不解释为什么,而是直接展示Win32下的汇编代码给大家,Linux下的大同小异。
x = y++ + x++; 004113DC mov eax,dword ptr [y] 004113DF add eax,dword ptr [x] 004113E2 mov dword ptr [x],eax 004113E5 mov ecx,dword ptr [x] 004113E8 add ecx,1 004113EB mov dword ptr [x],ecx 004113EE mov edx,dword ptr [y] 004113F1 add edx,1 004113F4 mov dword ptr [y],edx y = ++y + ++x; 004113F7 mov eax,dword ptr [y] 004113FA add eax,1 004113FD mov dword ptr [y],eax 00411400 mov ecx,dword ptr [x] 00411403 add ecx,1 00411406 mov dword ptr [x],ecx 00411409 mov edx,dword ptr [y] 0041140C add edx,dword ptr [x] 0041140F mov dword ptr [y],edx
|
总结一下规律:
一、i++是在整条语句执行完成后,才自增1的。也就是说,不管有多少个i++,都是在语句完成后,一个一个的累加的。
二、++i是在整条语句执行前进行运算的,也就是说,它执行的时间实际早于整条语句。
这里我们再来看试题。一开始是x=35+20=55,然后是执行x++,结果x=56;再执行y++,结果y=36。后来是先++x,结果x=57,再后来是++y,结果y=37,最后执行y=37+57=94。
作为函数参数传递时,问题会更复杂一些。这里我先说结论,有的是每个逗号分隔开的语句执行时都要完成++i和i++,有的则是最后统一完成。而且在不同的编译器下,结果是不一样的。比如下面的代码
void Test(int a, int b, int c) { }
int main( ) { int x=20;
Test(++x, ++x, ++x+1); }
|
在Win32中,a,b,c的值会是23,23,24,而在Linux下则会是23,23,22。
个人观点:本来i++和++i都是为了提高程序执行效率而存在的语法,现在被人出题成了这种几乎不可能使用的方式,就像我学会了屠龙术,却遍寻不到一条龙一样!要知道,如果有人将代码写成试题中的那样,他就不适合做程序员!