前面转载了[变态的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(收尾)工作.
此外,自增自减无非是编译器的具体实现问题,无需要太过纠结.