引言
最近上班想到书中所说的每种循环的执行效率是不同的,而具体情况是怎么样我也记不清了,乘着有时间来研究研究,所以写下了这片博文。本文通过查看汇编代码比较各循环的效率以及i++,++i,i--,--i在循环中使用的效率问题,仅供抛砖引玉,测试平台操作系统为ubuntu,CPU为intel i5 4440,编译器为gcc-4.8.2。
测试代码1
此段代码我们主要测试在i--,--i,i++,++i的情况下,for循环、dowhile循环、while循环之间的执行效率情况。
-
#include <stdio.h>
-
-
/* 用于测试i--的while,for,dowhile循环情况 */
-
void minus1 (void)
-
{
-
int i = 10;
-
-
/* i-- while循环 */
-
while (i--)
-
;
-
-
i = 10;
-
-
/* i-- dowhile循环 */
-
do
-
;
-
while (i--);
-
-
/* i-- for循环 */
-
for (i = 10; i != 0; i--)
-
;
-
}
-
-
/* 用于测试--i的while,for,dowhile循环情况 */
-
void minus (void)
-
{
-
int i = 10;
-
-
/* --i while循环 */
-
while (--i)
-
;
-
-
i = 10;
-
-
/* --i dowhile循环 */
-
do
-
;
-
while (--i);
-
-
/* --i for循环 */
-
for (i = 10; i != 0; --i)
-
;
-
}
-
-
/* 用于测试i++的while,for,dowhile循环情况 */
-
void plus1 (void)
-
{
-
int i = 0;
-
-
/* i++ while循环 */
-
while (i++ < 10)
-
;
-
-
i = 0;
-
-
/* i++ dowhile循环 */
-
do
-
;
-
while (i++ < 10);
-
-
/* i++ for循环 */
-
for (i = 0; i < 10; i++)
-
;
-
}
-
-
/* 用于测试++i的while,for,dowhile循环情况 */
-
void plus (void)
-
{
-
int i = 0;
-
-
/* ++i while循环 */
-
while (++i < 10)
-
;
-
-
i = 0;
-
-
/* ++i dowhile循环 */
-
do
-
;
-
while (++i < 10);
-
-
/* ++i for循环 */
-
for (i = 0; i < 10; ++i)
-
;
-
}
-
-
-
int main (int argc, char * argv[])
-
{
-
return 0;
-
}
好的,通过以上简单的代码,在linux下编译时加上{-g -Wall},再用{objdump -S 执行文件}命令即可查看运行文件的汇编代码,具体如下
-
#include <stdio.h>
-
-
void minus1 (void)
-
{
-
4004ed: 55 push %rbp
-
4004ee: 48 89 e5 mov %rsp,%rbp
-
int i = 10;
-
4004f1: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
-
-
while (i--) # while (i--)
-
4004f8: 90 nop # 空指令
-
4004f9: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
-
4004fc: 8d 50 ff lea -0x1(%rax),%edx # edx = rax - 1(rax的低32位为eax) 主循环
-
4004ff: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
-
400502: 85 c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
-
400504: 75 f3 jne 4004f9 <minus1+0xc> # 不等于0则跳转至4004f9 主循环
-
;
-
-
i = 10;
-
400506: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
-
-
do
-
;
-
while (i--); # do ... while (i--);
-
40050d: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
-
400510: 8d 50 ff lea -0x1(%rax),%edx # edx = rax - 1(rax的低32位为eax) 主循环
-
400513: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
-
400516: 85 c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
-
400518: 75 f3 jne 40050d <minus1+0x20> # 不等于0则跳转至40050d 主循环
-
-
for (i = 10; i != 0; i--) # for (i = 10; i != 0; i--)
-
40051a: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
-
400521: eb 04 jmp 400527 <minus1+0x3a> # 跳转至400527
-
400523: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
-
400527: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0进行比较 主循环
-
40052b: 75 f6 jne 400523 <minus1+0x36> # 比较结果不等于0则跳转至400523 主循环
-
;
-
}
-
-
void minus (void)
-
{
-
40052f: 55 push %rbp
-
400530: 48 89 e5 mov %rsp,%rbp
-
int i = 10;
-
400533: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
-
-
while (--i) # while (--i)
-
40053a: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
-
40053e: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
-
400542: 75 f6 jne 40053a <minus+0xb> # 比较结果不等于0则跳转至40053a 主循环
-
;
-
-
i = 10;
-
400544: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
-
-
do
-
;
-
while (--i); # do ... while (--i);
-
40054b: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
-
40054f: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
-
400553: 75 f6 jne 40054b <minus+0x1c> # 比较结果不等于0则跳转至40054b 主循环
-
-
for (i = 10; i != 0; --i) # for (i = 10; i != 0; --i)
-
400555: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
-
40055c: eb 04 jmp 400562 <minus+0x33> # 跳转至400562
-
40055e: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
-
400562: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
-
400566: 75 f6 jne 40055e <minus+0x2f> # 比较结果不等于0则跳转至40055e 主循环
-
;
-
}
-
-
void plus1 (void)
-
{
-
40056a: 55 push %rbp
-
40056b: 48 89 e5 mov %rsp,%rbp
-
int i = 0;
-
40056e: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
-
while (i++ < 10) # while (i++ < 10)
-
400575: 90 nop
-
400576: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
-
400579: 8d 50 01 lea 0x1(%rax),%edx # edx = rax + 1(rax的低32位为eax) 主循环
-
40057c: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
-
40057f: 83 f8 09 cmp $0x9,%eax # eax与9比较 主循环
-
400582: 7e f2 jle 400576 <plus1+0xc> # 比较结果不成立则跳转至400576 主循环
-
;
-
-
i = 0;
-
400584: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
-
do
-
;
-
while (i++ < 10); # while (i++ < 10);
-
40058b: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
-
40058e: 8d 50 01 lea 0x1(%rax),%edx # edx = rax + 1(rax的低32位为eax) 主循环
-
400591: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
-
400594: 83 f8 09 cmp $0x9,%eax # eax与9比较 主循环
-
400597: 7e f2 jle 40058b <plus1+0x21> # 比较结果不成立则跳转至40058b 主循环
-
-
for (i = 0; i < 10; i++) # for (i = 0; i < 10; i++)
-
400599: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) # i = 0
-
4005a0: eb 04 jmp 4005a6 <plus1+0x3c> # 跳转至4005a6
-
4005a2: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
-
4005a6: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
-
4005aa: 7e f6 jle 4005a2 <plus1+0x38> # 比较结果不成立则跳转至4005a2 主循环
-
;
-
}
-
-
void plus (void)
-
{
-
4005ae: 55 push %rbp
-
4005af: 48 89 e5 mov %rsp,%rbp
-
int i = 0;
-
4005b2: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
-
while (++i < 10) # while (++i < 10)
-
4005b9: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
-
4005bd: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
-
4005c1: 7e f6 jle 4005b9 <plus+0xb> # 比较结果不成立则跳转至4005b9 主循环
-
;
-
-
i = 0;
-
4005c3: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
-
do
-
;
-
while (++i < 10); # while (++i < 10);
-
4005ca: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
-
4005ce: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
-
4005d2: 7e f6 jle 4005ca <plus+0x1c> # 比较结果不成立则跳转至4005b9 主循环
-
-
for (i = 0; i < 10; ++i) # for (i = 0; i < 10; ++i)
-
4005d4: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) # i = 0
-
4005db: eb 04 jmp 4005e1 <plus+0x33> # 跳转至4005e1
-
4005dd: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
-
4005e1: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
-
4005e5: 7e f6 jle 4005dd <plus+0x2f> # 比较结果不成立则跳转至4005dd 主循环
-
;
-
}
根据上述汇编代码,将其制成表格
|
while主循环指令数
|
do...while主循环指令数
|
for主循环指令数
|
i--
|
5
|
5
|
3
|
--i
|
3
|
3
|
3
|
i++
|
5
|
5
|
3
|
++i
|
3
|
3
|
3
|
小结
根据表格可清楚地看出,在while循环,do...while循环和for循环中,最优的循环效率为3条汇编指令,最不理想的情况为5条指令,对应的5条指令是在while循环和do...while循环中使用i--和i++控制循环的情况下产生的,效率较低,而其他情况下都为3条指令实现循环。在其中比较突出的是for循环,在for循环中无论使用i--,--i,i++还是++i控制循环都是最优的3条指令结构。而使用--i和++i控制循环结构的情况下,无论哪一种循环都是最优的主循环结构(3条指令)。
阅读(3573) | 评论(0) | 转发(0) |