前端面试的时候老总居然问这个问题,有点震惊……
#include <stdio.h> #include <stdlib.h> void main() { int i = 1; printf("%d,%d,%d,%d,%d,%d ", i,i++,++i,i--,i++,--i); system("pause"); }
作为一个以前压根没深入研究过C语言运行机制的人,这个问题真是难住我了
如果你的回答是输出
1,1,3,3,2,2
恭喜你跟我错得一样,老总说这跟语言没关系,所有语言的思路都一样……但是明明JS的运行结果就是上面那个嘛……
在VS下,运行结果是
2,1,2,1,0,2
震惊之余,看了下反汇编的代码
int i = 1; 00DF3C0E mov dword ptr [i],1 printf("%d,%d,%d,%d,%d,%d ", i,i++,++i,i--,i++,--i);//看看结果是从右往左开始运算 00DF3C15 mov eax,dword ptr [i] 00DF3C18 sub eax,1 00DF3C1B mov dword ptr [i],eax //--i,i=0 00DF3C1E mov ecx,dword ptr [i] 00DF3C21 mov dword ptr [ebp-0D0h],ecx //将i复制一份到 dword ptr [ebp-0D0h]这个地址,0 00DF3C27 mov edx,dword ptr [i] 00DF3C2A add edx,1 00DF3C2D mov dword ptr [i],edx //i++,i=1 00DF3C30 mov eax,dword ptr [i] 00DF3C33 mov dword ptr [ebp-0D4h],eax //将i复制一份到 dword ptr [ebp-0D4h]这个地址,1 00DF3C39 mov ecx,dword ptr [i] 00DF3C3C sub ecx,1 00DF3C3F mov dword ptr [i],ecx //i--,i=0 00DF3C42 mov edx,dword ptr [i] 00DF3C45 add edx,1 00DF3C48 mov dword ptr [i],edx //++i,i=1 00DF3C4B mov eax,dword ptr [i] 00DF3C4E mov dword ptr [ebp-0D8h],eax //将结果复制一份到dword ptr [ebp-0D8h]这个地址,1 00DF3C54 mov ecx,dword ptr [i] 00DF3C57 add ecx,1 00DF3C5A mov dword ptr [i],ecx //i++,i=2 00DF3C5D mov esi,esp 00DF3C5F mov edx,dword ptr [i] //edx = 2 00DF3C62 push edx //2入 00DF3C63 mov eax,dword ptr [ebp-0D0h] //eax = 0 00DF3C69 push eax //0入 00DF3C6A mov ecx,dword ptr [ebp-0D4h] //ecx = 1 00DF3C70 push ecx //1入 00DF3C71 mov edx,dword ptr [i] //edx = 2 00DF3C74 push edx //2入 00DF3C75 mov eax,dword ptr [ebp-0D8h] //eax = 1 00DF3C7B push eax //1入 00DF3C7C mov ecx,dword ptr [i] //ecx = 2 00DF3C7F push ecx //2入 00DF3C80 push 0DF59CCh 00DF3C85 call dword ptr ds:[0DF9114h] 00DF3C8B add esp,1Ch 00DF3C8E cmp esi,esp 00DF3C90 call __RTC_CheckEsp (0DF1136h)
虽然其中部分操作不知道是做什么用的,但是看最下面的数字,可以发现就是最终的输出结果
从其中可以分析出,在运算过程中,往内存中写入了多个新的值(比如新产生的dword ptr [ebp-0D0h])
碰到i++,i--的时候,会从一个新的内存地址中取值
碰到++i,--i,i的时候,会从最初的内存地址中取值,也就是获取i计算的最终值
那么,我们可以发现,在计算i++,i--之前,i的结果会缓存到内存中,以便后面使用
这样,结果就迎刃而解了
PS:
运算是自右往左的方向计算的,压栈也是
如果我们在最后面再加一个参数i,会发现反汇编的代码最开始的部分没变,也就是说,首先会计算自增,自减部分
如果在其中加入i+1这样的操作,会发现这部分代码是在压栈的同时计算的