#include<stdio.h>
int main()
{
int i = 0;
printf("%d,%d,%d\n", i++, --i, i++);
return 0;
}
今天看到了一段很短的代码,问结果?
1:将i(此时为0)压入栈中,此后做+1运算后将1赋给i。
2:将i做-1运算,也就是1-1=0,然后将0值赋给i,然后将i(此时为0)压入栈中。
3:类似步骤1,将i(此时为0)压入栈中,然后做+1运算后将1赋给i。
可以看到,上面三步压入栈中的数据为0,0,0。也就是我们预期的结果应该是0,0,0。OK,接下来只需要验证我们的结果就就可以啦~
嗯?结果和预想的不一样?wtf?看到这个结果的时候,我真的认为自己之前的知识是不是出了什么问题,再去看了看++和--的知识发现没有问题啊,可是结果运用之前的知识分析就是不对啊。~那到底是那里出问题了呢?~这个时候就需要我们去调试代码看看它具体的处理过程了。下面是它的汇编代码。
printf("%d,%d,%d\n", i++, --i, i++);
00DE1805 mov eax,dword ptr [i]
00DE1808 mov dword ptr [ebp-0D0h],eax
00DE180E mov ecx,dword ptr [i]
00DE1811 add ecx,1
00DE1814 mov dword ptr [i],ecx
00DE1817 mov edx,dword ptr [i]
00DE181A sub edx,1
00DE181D mov dword ptr [i],edx
00DE1820 mov eax,dword ptr [i]
00DE1823 mov dword ptr [ebp-0D4h],eax
00DE1829 mov ecx,dword ptr [i]
00DE182C add ecx,1
00DE182F mov dword ptr [i],ecx
00DE1832 mov edx,dword ptr [ebp-0D0h]
00DE1838 push edx
00DE1839 mov eax,dword ptr [i]
00DE183C push eax
00DE183D mov ecx,dword ptr [ebp-0D4h]
00DE1843 push ecx
00DE1805 mov eax,dword ptr [i]
00DE1808 mov dword ptr [ebp-0D0h],eax
00DE180E mov ecx,dword ptr [i]
00DE1811 add ecx,1
00DE1814 mov dword ptr [i],ecx
1:将i(此时为0)压入eax寄存器,将eax内的值赋给一个临时量1(地址为[ebp-0D0h]),然后将i(此时为0)压入ecx寄存器,ecx+1运算后将值赋给i(此时i为1)。(对应汇编的2-6)
00DE1817 mov edx,dword ptr [i]
00DE181A sub edx,1
00DE181D mov dword ptr [i],edx
2:将i(此时为1)压入edx寄存器,edx-1后将值赋给i(此时i为0)。(对应汇编的7-9)
00DE1820 mov eax,dword ptr [i]
00DE1823 mov dword ptr [ebp-0D4h],eax
00DE1829 mov ecx,dword ptr [i]
00DE182C add ecx,1
00DE182F mov dword ptr [i],ecx
3:将i(此时为0)压入eax寄存器,将eax内的值赋给一个临时量2(地址为[ebp-0D4h]),然后将i(此时为0)压入ecx寄存器,ecx+1运算后将值赋给i(此时i为1)。(对应汇编10-14)
00DE1832 mov edx,dword ptr [ebp-0D0h]
00DE1838 push edx
00DE1839 mov eax,dword ptr [i]
00DE183C push eax
00DE183D mov ecx,dword ptr [ebp-0D4h]
00DE1843 push ecx
4:接下来是压参过程,依次压入临时量1(地址为[ebp-0D0h]),i(此时为0),临时量2(地址为[ebp-0D4h])。
总结:
可以看到上述过程在处理过程中并没有像我们想象的那样,处理一个参数压入一个参数。i++是先将值保存在一个临时量中,然后做运算改变i的值。而--i,是先做运算改变i的值,注意这里是和预想结果不一样的重点,它做运算后将值赋给i并不会将值保存在临时量中,而是等所有运算结束后压入i的值。这里就引发一个问题,如果--i不是最后一个做运算的,那么它的后续运算(也就是第一个参数i++)将会改变i的值。做完运算后统一压参数的时候,i++都是压入它们未做运算前的临时量,所以它们和预想的结果一致。而--i是等所有运算结束后压入i值,如果这个过程是独立的,没有其他运算参与那么没有问题,可是这里因为还有后续的i++(它最终将i的值运算为0),就导致了结果和预想的不一致。
解决方案:
压--i这个参数可以参考i++的过程,如果它在运算结束后将值赋给一个临时量,在所有运算结束后,压入这个临时量,那么逻辑过程就应该和预想的一致了。