分类: C/C++
2008-04-04 16:53:23
|
这个例子是我一个朋友发给我的,他告诉我他一直都想不通为什么在VC6.0下面会输出6。我接过例子的时候也以为结果是5,至少我在GNU Gcc下面编译运行是5。可是VC6.0下面输出却是6。
这回,我编译后用debug调试,打开disassembly查看汇编代码。的确,一看汇编后,什么事情都变得明朗。
|
ebp是运行时堆栈的栈低指针。ebp-10h地址上存放了k的值([ebp-10h]表示ebp-10h地址上的内容),运行int k = 1;后,[ebp-10h]的值是1。
接着运行printf("%d\n",(++k)+(++k));语句。printf()实际上是库函数,在调用printf()函数前,需要先计算(++k)+(++k)的值,然后把该值压到栈顶,以传送给printf()的形参。
关键还是(++k)+(++k)的计算问题。
C语言中只有四个运算存在规定的求值顺序:&&、||、?:和,(注意:此处的,是逗号操作符,并非函数参数列表的分隔符,)。
由于()的优先级作用,会先计算++k,但是并没有规定两边(++k)的求值顺序。所以,有可能是左边的++k先求值,也有可能是+右边的++k先求值。但无论如何,两次的++k之后,k的值是3 。然而,为何计算结果为什么不是2 + 3 或者是 3 + 2 呢?这似乎与求值顺序无关。
但是,编译器似乎没有预计得到,计算其中一边的表达式算影响到另一边的表达式的结果。所以,编译器认为两边的++k是相等的。
mov edx,dword ptr [ebp-10h] //把k的值放到edx寄存器中
add edx,1 //计算++k
mov dword ptr [ebp-10h],edx //再把++k的结果放回ebp-10h地址中,此时k=2
mov eax,dword ptr [ebp-10h] //把k值复制到eax寄存器中
add eax,1 //计算++k
mov dword ptr [ebp-10h],eax //再把++k的结果放回ebp-10h地址中,此时k=3
mov ecx,dword ptr [ebp-10h] //把k值复制到ecx中
add ecx,dword ptr [ebp-10h] //计算k+k的值
push ecx //将k+k的值压栈,以传送给printf的形参
听说,这个现象叫做存储器别名使用(memory aliasing)。反正,不要这么用就可以避免了。