实现无限循环时,使用while(1)
、for(;;)
和goto
有什么区别吗?
谢谢, Chenz
实现无限循环时,使用while(1)
、for(;;)
和goto
有什么区别吗?
谢谢, Chenz
它们是等价的,即使你关闭优化器。
例如:
#include <stdio.h>
extern void f(void) {
while(1) {
putchar(' ');
}
}
extern void g(void) {
for(;;){
putchar(' ');
}
}
extern void h(void) {
z:
putchar(' ');
goto z;
}
使用gcc -O0
编译会使得这3个函数的汇编代码等价:
f:
; [ EXTERNAL ]
;
+00000 00000fb4 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fb8 00708DE2 add r7,sp,#0x0
+00008 00000fbc 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fc0 0A0000EB bl putchar (stub)
+00010 00000fc4 FCFFFFEA b loc_000008
;
;
g:
; [ EXTERNAL ]
;
+00000 00000fc8 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fcc 00708DE2 add r7,sp,#0x0
+00008 00000fd0 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fd4 050000EB bl putchar (stub)
+00010 00000fd8 FCFFFFEA b loc_000008
;
;
h:
; [ EXTERNAL ]
;
+00000 00000fdc 80402DE9 stmdb sp!,{r7,lr}
+00004 00000fe0 00708DE2 add r7,sp,#0x0
+00008 00000fe4 2000A0E3 loc_000008: mov r0,#0x20
+0000c 00000fe8 000000EB bl putchar (stub)
+00010 00000fec FCFFFFEA b loc_000008
我刚刚比较了gcc的未优化汇编输出:
# cat while.c
int main() {
while(1) {};
return 0;
}
# cat forloop.c
int main() {
for (;;) { };
return 0;
}
# gcc -S while.c
# gcc -S forloop.c
比较汇编文件:
# diff forloop.s while.s
1c1
< .file "forloop.c"
---
> .file "while.c"
正如您所看到的,没有明显的差异。以下是输出结果:
# cat while.s
.file "while.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
.L2:
jmp .L2 # this is the loop in both cases
.size main, .-main
.ident "GCC: (GNU) 4.4.3"
.section .note.GNU-stack,"",@progbits
虽然这并不是技术上的证明它们是相同的,但我认为在99.9%的情况下它们是相同的。
生成的汇编代码几乎没有区别。这更多是一个风格问题:
Goto - 简直难看:向后跳转,没有明确的无限循环块
while(1) - 更好,需要“虚拟”条件,但你经常会被编译器(警告级别4)或静态分析工具警告
for(;;) 可能不是最漂亮的,但在我看来最适合,因为这个结构不能有任何其他意义(与while相比)。但有些人出于“相同”的原因更喜欢while(1)...
for (;;)
而不是while (1)
的常见原因是静态分析工具(以及某些具有特定警告级别的编译器)经常会抱怨while循环。for (;;)
(以使Lint满意),但我对while (1)
没有任何问题。while(1)
和 for(;;)
是完全等价的,这两种写法都是编写无限循环的常用习语。
我建议避免使用 goto
:如果需要跳出无限循环或继续下一次迭代,请使用 break
和 continue
。
没有固定要求。使用最容易理解的方式即可。
true
的实现方式取决于编译器。#define TRUE 1
#define TRUE (-1)
AND false被实现为
#define FALSE 0
while (1)
等同于while (true)
,因为0被认为是假。
while (1) == for (; ;)
,因为它们没有停止条件。
在汇编语言中,它被翻译为:
:loop
...
...
...
goto loop
ret
或exit
指令,它被视为无限循环。从我回忆起的“反汇编年代”来看,这不会有太大的区别(编译器足够聪明)。在我看来,这更多是关于美学方面的。
for(;;)
可以让你定义#define ever (;;)
并使用for ever {...}
;) - kennytm