前面轉載了[變態的C自增]這篇文章後,自己又總結了一下關鍵點:
1、局部變量i,是保存在棧上的,沒有拷貝!
2、後綴++,和前綴++的求值時間的先後問題
3、後綴++的使用甚至在"="賦值操作之後。
但是,上述文章並沒有對gcc和vc進行分析。在兩個變量進行運算的時候,兩者的代碼運算的結果還是一致的。當多於兩個變量運算的時候,結果就出現分歧了。
代碼如下:
#include<stdio.h>
int main()
{
int a = 3;
a = ++a*++a*++a;
printf("%d/n",a);
return 0;
}
0040D76B add ecx,1
0040D76E mov dword ptr [ebp-4],ecx
0040D771 mov edx,dword ptr [ebp-4]
0040D774 imul edx,dword ptr [ebp-4]
0040D778 mov eax,dword ptr [ebp-4]
0040D77B add eax,1
0040D77E mov dword ptr [ebp-4],eax
0040D781 imul edx,dword ptr [ebp-4]
0040D785 mov dword ptr [ebp-4],edx
先加二次,此時a=5,然後5*5=25 --> edx
a又加一,a=6.最後執行edx與a所在地址的值相乘,即25*6=150
VS2008的彙編代碼如下:
004113C5 mov eax,dword ptr [a]
004113C8 add eax,1
004113CB mov dword ptr [a],eax
004113CE mov ecx,dword ptr [a]
004113D1 add ecx,1
004113D4 mov dword ptr [a],ecx
004113D7 mov edx,dword ptr [a]
004113DA add edx,1
004113DD mov dword ptr [a],edx
004113E0 mov eax,dword ptr [a]
004113E3 imul eax,dword ptr [a]
004113E7 imul eax,dword ptr [a]
004113EB mov dword ptr [a],eax
連續加了三次,此時a=6,然後6*6*6=216 --> [a]地址所存放在的地方
gcc4.3.2的彙編代碼如下:
movl $3, -8(%ebp)
addl $1, -8(%ebp)
addl $1, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, %edx
imull -8(%ebp), %edx
addl $1, -8(%ebp)
movl -8(%ebp), %eax
imull %edx, %eax
movl %eax, -8(%ebp)
與vc6.0的相似,a的值存放的位置是[ebp-8]的地方,然後自增二次,此時a=5.然後相乘結果放到edx中.a又自增,此時a=6,相乘的結果放到eax中,然後賦值給[ebp-8](即文中的-8(%ebp)).a的值即爲5*5*6=150.
PS:微軟真是強大,VS2008連具體變量的地址都不讓我看了.文中,我只是分析了關鍵部分的代碼,其它部分的代碼並未分析.下一階段重點分析這一部分,即例程的prolog(序幕)與epilog(收尾)工作.
此外,自增自減無非是編譯器的具體實現問題,無需要太過糾結.