C语言两种for循环写法分析

每个C程序员都知道同一个for循环语句可以有两种写法:

A: for (i = 0; i < cnt; i++){ }

B: for (i = cnt; i > 0; i--){ }

前几天,DEBUG的时候, 发现采用A写法的代码反汇编出来有BUG.当时没有时间记录,环境也没有保存下来.今天尝试重现,又没来出现上次的问题...很奇怪.

很久很久以前也听说过这两种写法有区别,今天就顺便分析一下,也算没有白忙.


编译环境: mipsisa32-xlr-linux-gcc 3.4.3

测试代码见附件: raw_socket.c

A反汇编之后的代码如下:

C语言两种for循环写法分析_第1张图片

B反汇编之后的代码如下:

C语言两种for循环写法分析_第2张图片

对A的分析:

401158: 将 i 清零

40115c: 将 i 的值加载到寄存器 v0

401160: 将 cnt 的值加载到寄存器 v1

401164: 比较 v0 是否小于 v1 即 i 是否小于 cnt. 如果 i < cnt 则 v0 的值为 1 否则 v0 的值为 0

401168: 如果 v0 的值为 0 即 i > cnt, 则跳到 4011a8 地址执行, 即跳出 for 循环

...

4011a0: 跳到 40115c 重新开始 for 循环

4011a4: 把 v0 即 i 的值写入内存. 由于mips的流水行机制, 在上一条语句真正跳转前,这条语句会被执行


对B的分析:

401158: 将 cnt 的值加载到寄存器 v0

40115c: 将 v0 的值赋给 i, 即将 cnt 的值赋给 i 

401160: 将 i 的值加载到寄存器 v0 (这一条有必要么?)

401164: 如果 v0 的值小于等于 0, 即 i <= 0, 则跳到 4011a4 处执行, 即跳出 for 循环

...

40119c: 跳到 401160 地址执行, 重新开始 for 循环

4011a0:  把 v0 即 i 的值写入内存.


通过上面的分析可以看出A要比B多一条语句: A的401160. 每次for循环, A都要从内存中多加载一次cnt的值.

内存的读取一般远远小于CPU的执行速度.A的效率应该不如B高.


将同样的代码,在x86上编译,反汇编.

系统: Fedora 17 x86

编译器: gcc 4.7.2


A写法的反汇编结果:

B写法的反汇编结果:

C语言两种for循环写法分析_第3张图片

A写法同样多了对cnt内存的读取...

你可能感兴趣的:(c,c,linux,linux,linux,汇编,编译器)