printf(”%d\n”, i++ * ++i + i– * –i);
在吉林大学的视频c教程中, 上式值为18.她的解法是前缀优先于后缀,所以就是3 * 4 + 3 * 2。在gcc中得到的结果是25。
这种行为是标准未定义的。
可以通过反汇编来查看gcc的行为。如下,我们看看调用printf之前gcc是如何操作i。
80483b5: c7 45 f8 03 00 00 00 movl $0×3,0xfffffff8(%ebp)
给i赋值3。
80483bc: 83 45 f8 01 addl $0×1,0xfffffff8(%ebp)
加1。i==4
80483c0: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
80483c3: 89 c2 mov %eax,%edx
80483c5:
0f af 55 f8 imul 0xfffffff8(%ebp),%edx
计算此时的i*i。 16
80483c9: 83 6d f8 01 subl $0×1,0xfffffff8(%ebp)
把i减1,即i==3。
80483cd: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
80483d0: 0f af 45 f8 imul 0xfffffff8(%ebp),%eax
计算i*i,即9。
80483d4: 8d 04 02 lea (%edx,%eax,1),%eax
把上面两个乘的结果加起来,放入%eax。
80483d7: 83 45 f8 01 addl $0×1,0xfffffff8(%ebp)
80483db: 83 6d f8 01 subl $0×1,0xfffffff8(%ebp)
把i加1,再减1。
80483df: 89 44 24 04 mov %eax,0×4(%esp)
%eax就是最后结果,即25
80483e3: c7 04 24 d0 84 04 08 movl $0×80484d0,(%esp)
80483ea: e8 c9 fe ff ff call 80482b8
另外,如果你把gcc的优化级别调高一些,你会发现结果也是18。
如果你把i类型改成volatile int,结果是24。(3 * 4
+ 4 * 3)
这个问题的关键是看编译器怎么处理寄存器和内存之间的关系,已经超出了
标准所规定的范围。实际中这种代码是应该避免的。