GCC下宏扩展后的++i

听讨论的时候,遇到一题是关于++i*++i的——这样的讨论意义不大,却也可以一窥编译器对相关问题的处理。

原题如下

相关代码说明如下

  
  
#include < stdio.h > #define POWER(X) X*X int main() { int ch = 8 ; int sum = POWER(ch ++ ); sum = POWER( ++ ch); return 0 ; }

如果添加printf输出,其第一个sum = 64,第二个sum = 144

将上面的进行汇编编译得到。

gcc -S test.c

程序main的主要汇编代码

  
  
main: pushl %ebp movl %esp, %ebp subl $ 16 , %esp movl $ 8 , - 8 (%ebp) movl - 8 (%ebp), %eax imull - 8 (%ebp), %eax movl %eax, - 4 (%ebp) addl $ 1 , - 8 (%ebp) addl $ 1 , - 8 (%ebp) addl $ 1 , - 8 (%ebp) addl $ 1 , - 8 (%ebp) movl - 8 (%ebp), %eax imull - 8 (%ebp), %eax movl %eax, - 4 (%ebp) movl $ 0 , %eax leave ret

少去进栈出栈的操作,i++*i++产生的汇编代码是

  
  
     movl - 8 (%ebp), %eax imull - 8 (%ebp), %eax movl %eax, - 4 (%ebp) addl $ 1 , - 8 (%ebp) addl $ 1 , - 8 (%ebp)

++i*++i产生的汇编代码是

  
  
addl $ 1 , - 8 (%ebp) addl $ 1 , - 8 (%ebp) movl - 8 (%ebp), %eax imull - 8 (%ebp), %eax

由上面的代码可以看出

1)i++的自增操作是在整个乘法完成之后才进行的,而++i的操作则是在乘法之前进行。

2)movl和imull总是连续出现,进行乘法的时候,左右的操作数是从同一块内存取出来的,因此计算结果肯定是完全平方数。

找到一篇相似的文章《分析gcc下的i++与++i》gfw),在后续讨论三个i++的情况。后面还有总结,先一并摘抄过来。

++i*i++*++i的汇编代码为  

  
  
movl $ 8 , - 8 (%ebp) addl $ 1 , - 8 (%ebp) movl - 8 (%ebp), %eax imull - 8 (%ebp), %eax addl $ 1 , - 8 (%ebp) imull - 8 (%ebp), %eax movl %eax, - 4 (%ebp) addl $ 1 , - 8 (%ebp) leave ret

摘录

分析一下上面的代码,结论就很清晰了,所有的i++操作会在整个表达式计算完后才计算,除了最左边的乘法会从同一块内存取操作数外,后续的乘法的作操作数就是直接取的上次计算的结果。

  
  
总结一下: 1.从左向右计算 2.最左边的乘法从同一内存取操作数,因此肯定是完全平方数 3.所有的i ++ 可以替换成i 4.所有的 ++ i先计算增一,再取增一后的值
比如计算 i++*++i*++i*i++*++i (i=3): 结果是 4×4×5×5×6=2400.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值