大家都知道每种循环对应的效率是不同的,书中都说在循环中使用减法的效率是比加法的效率高的,具体情况是怎么样,我们将详细列出各循环的执行效率问题。本文通过查看汇编代码比较各循环的效率以及i++,++i,i--,--i在循环中使用的效率问题,仅供抛砖引玉,测试平台为intel i5 4440,编译器为gcc-4.8.2
测试代码1
此段代码我们主要测试在i--,--i,i++,++i的情况下,for循环、dowhile循环、while循环之间的执行效率情况
1 #include <stdio.h>
3 /* 用于测试i--的while,for,dowhile循环情况 */
4 void minus1 (void)
6 int i = 10;
8 /* i-- while循环 */
9 while (i--)
10 ;
12 i = 10;
14 /* i-- dowhile循环 */
15 do
16 ;
17 while (i--);
19 /* i-- for循环 */
20 for (i = 10; i != 0; i--)
21 ;
22 }
24 /* 用于测试--i的while,for,dowhile循环情况 */
25 void minus (void)
26 {
27 int i = 10;
29 /* --i while循环 */
30 while (--i)
31 ;
33 i = 10;
35 /* --i dowhile循环 */
36 do
37 ;
38 while (--i);
40 /* --i for循环 */
41 for (i = 10; i != 0; --i)
42 ;
43 }
45 /* 用于测试i++的while,for,dowhile循环情况 */
46 void plus1 (void)
47 {
48 int i = 0;
50 /* i++ while循环 */
51 while (i++ < 10)
52 ;
54 i = 0;
56 /* i++ dowhile循环 */
57 do
58 ;
59 while (i++ < 10);
61 /* i++ for循环 */
62 for (i = 0; i < 10; i++)
63 ;
64 }
66 /* 用于测试++i的while,for,dowhile循环情况 */
67 void plus (void)
68 {
69 int i = 0;
71 /* ++i while循环 */
72 while (++i < 10)
73 ;
75 i = 0;
77 /* ++i dowhile循环 */
78 do
79 ;
80 while (++i < 10);
82 /* ++i for循环 */
83 for (i = 0; i < 10; ++i)
84 ;
85 }
88 int main (int argc, char * argv[])
89 {
90 return 0;
测试代码1所生成的汇编代码如下:
1 #include <stdio.h>
3 void minus1 (void)
5 4004ed: 55 push %rbp
6 4004ee: 48 89 e5 mov %rsp,%rbp
7 int i = 10;
8 4004f1: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
10 while (i--) # while (i--)
11 4004f8: 90 nop # 空指令
12 4004f9: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
13 4004fc: 8d 50 ff lea -0x1(%rax),%edx # edx = rax - 1(rax的低32位为eax) 主循环
14 4004ff: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
15 400502: 85 c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
16 400504: 75 f3 jne 4004f9 <minus1+0xc> # 不等于0则跳转至4004f9 主循环
17 ;
19 i = 10;
20 400506: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
22 do
23 ;
24 while (i--); # do ... while (i--);
25 40050d: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
26 400510: 8d 50 ff lea -0x1(%rax),%edx # edx = rax - 1(rax的低32位为eax) 主循环
27 400513: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
28 400516: 85 c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
29 400518: 75 f3 jne 40050d <minus1+0x20> # 不等于0则跳转至40050d 主循环
31 for (i = 10; i != 0; i--) # for (i = 10; i != 0; i--)
32 40051a: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
33 400521: eb 04 jmp 400527 <minus1+0x3a> # 跳转至400527
34 400523: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
35 400527: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0进行比较 主循环
36 40052b: 75 f6 jne 400523 <minus1+0x36> # 比较结果不等于0则跳转至400523 主循环
37 ;
38 }
40 void minus (void)
41 {
42 40052f: 55 push %rbp
43 400530: 48 89 e5 mov %rsp,%rbp
44 int i = 10;
45 400533: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
47 while (--i) # while (--i)
48 40053a: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
49 40053e: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
50 400542: 75 f6 jne 40053a <minus+0xb> # 比较结果不等于0则跳转至40053a 主循环
51 ;
53 i = 10;
54 400544: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
56 do
57 ;
58 while (--i); # do ... while (--i);
59 40054b: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
60 40054f: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
61 400553: 75 f6 jne 40054b <minus+0x1c> # 比较结果不等于0则跳转至40054b 主循环
63 for (i = 10; i != 0; --i) # for (i = 10; i != 0; --i)
64 400555: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) # i = 10
65 40055c: eb 04 jmp 400562 <minus+0x33> # 跳转至400562
66 40055e: 83 6d fc 01 subl $0x1,-0x4(%rbp) # i = i - 1 主循环
67 400562: 83 7d fc 00 cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
68 400566: 75 f6 jne 40055e <minus+0x2f> # 比较结果不等于0则跳转至40055e 主循环
69 ;
70 }
72 void plus1 (void)
73 {
74 40056a: 55 push %rbp
75 40056b: 48 89 e5 mov %rsp,%rbp
76 int i = 0;
77 40056e: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
79 while (i++ < 10) # while (i++ < 10)
80 400575: 90 nop
81 400576: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
82 400579: 8d 50 01 lea 0x1(%rax),%edx # edx = rax + 1(rax的低32位为eax) 主循环
83 40057c: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
84 40057f: 83 f8 09 cmp $0x9,%eax # eax与9比较 主循环
85 400582: 7e f2 jle 400576 <plus1+0xc> # 比较结果不成立则跳转至400576 主循环
86 ;
88 i = 0;
89 400584: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
91 do
92 ;
93 while (i++ < 10); # while (i++ < 10);
94 40058b: 8b 45 fc mov -0x4(%rbp),%eax # eax = i 主循环
95 40058e: 8d 50 01 lea 0x1(%rax),%edx # edx = rax + 1(rax的低32位为eax) 主循环
96 400591: 89 55 fc mov %edx,-0x4(%rbp) # i = edx 主循环
97 400594: 83 f8 09 cmp $0x9,%eax # eax与9比较 主循环
98 400597: 7e f2 jle 40058b <plus1+0x21> # 比较结果不成立则跳转至40058b 主循环
100 for (i = 0; i < 10; i++) # for (i = 0; i < 10; i++)
101 400599: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) # i = 0
102 4005a0: eb 04 jmp 4005a6 <plus1+0x3c> # 跳转至4005a6
103 4005a2: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
104 4005a6: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
105 4005aa: 7e f6 jle 4005a2 <plus1+0x38> # 比较结果不成立则跳转至4005a2 主循环
106 ;
107 }
109 void plus (void)
110 {
111 4005ae: 55 push %rbp
112 4005af: 48 89 e5 mov %rsp,%rbp
113 int i = 0;
114 4005b2: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
116 while (++i < 10) # while (++i < 10)
117 4005b9: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
118 4005bd: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
119 4005c1: 7e f6 jle 4005b9 <plus+0xb> # 比较结果不成立则跳转至4005b9 主循环
120 ;
122 i = 0;
123 4005c3: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
125 do
126 ;
127 while (++i < 10); # while (++i < 10);
128 4005ca: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
129 4005ce: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
130 4005d2: 7e f6 jle 4005ca <plus+0x1c> # 比较结果不成立则跳转至4005b9 主循环
132 for (i = 0; i < 10; ++i) # for (i = 0; i < 10; ++i)
133 4005d4: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) # i = 0
134 4005db: eb 04 jmp 4005e1 <plus+0x33> # 跳转至4005e1
135 4005dd: 83 45 fc 01 addl $0x1,-0x4(%rbp) # i = i + 1 主循环
136 4005e1: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
137 4005e5: 7e f6 jle 4005dd <plus+0x2f> # 比较结果不成立则跳转至4005dd 主循环
138 ;
139 }
可以从汇编代码得出如下表格