“for(;;)”无限循环的习惯用法是否正确归因于PDP-11 C编译器?
最近我发现这篇文章声称喜欢for(;;)
over while(1)
无限循环的想法之所以出现,是因为最初在PDP-11上可用的C编译器为while(1)
生成了额外的机器指令。
顺便说一句,即使是Visual C ++警告也倾向于前者 。
这种for(;;)
成语的归属是多么现实?
这是V7 Unix编译器cc
生成的内容(使用SIMH和来自TUHS的图像):
$ cat>ac main(){ while(1); } $ cat>bc main(){ for(;;); } $ cc -S ac $ cc -S bc
ac
( while
)编译为:
.globl _main .text _main: ~~main: jsr r5,csv jbr L1 L2:L4:tst $1 jeq L5 jbr L4 L5:L3:jmp cret L1:jbr L2 .globl .data
而bc
( for
)变为:
.globl _main .text _main: ~~main: jsr r5,csv jbr L1 L2:L4:jbr L4 L5:L3:jmp cret L1:jbr L2 .globl .data
因此,在不使用优化时for(;;)
编译为更少的指令至少是正确的。 但是,使用-O
进行编译时,两个程序都会生成完全相同的程序集:
.globl _main .text _main: ~~main: jsr r5,csv L4:jbr L4 .globl .data
当我添加一个printf("Hello");
的循环体printf("Hello");
,程序仍然是一样的。
因此,成语可能源于PDP-11机器语言,但到了1979年,差异已经基本上无关紧要了。
原来的K&R中明确提到了“for(;;)”成语。 这对我来说足够了:)
要注意某些“明智的归属”,因为缺乏背景,往往是虚假的秘密。 OP标记了C和C ++的消息。
现在,K&R可以成为关于C历史的半神,但肯定不能被认为是C ++的权威。 此外,编译器优化可以在C ++中发挥基本作用,但通常被C系统程序员视为“滥用”(他们喜欢将C视为“带表达式的汇编程序”,而不是“高级语言”)。
今天的编译器很可能会生成完全相同的代码(这可以很容易地certificate),并且使用其中一个或更多的东西更多的是品味 ,然后是另一个。
在这个意义上,我倾向于赞成for(;;)
因为我可以很容易地把它读作“ 永远 ”而while(true)
读作“ 当这个真实的东西是真的 ”时,让你想象它是否能够均匀是假的…… 2毫秒的脑子浪费了! (但这是个人意见:我知道很多人必须考虑更多for(;;)
while(true)
不是while(true)
)
然而,我也可以将它们都识别为“图形表示”(实际上没有阅读文本,只是通过摄影记忆看它们看起来如何通过摄影记忆)指向同一个知识概念(留在这里,直到有人将你从内部踢开)。
关于MS警告,有时它会使你免于写错表达式(如true||a
)。 但显然是滥用,并且不应该出现,因为里面没有操作的琐碎表达。 Nerveless,MS编译器在两种情况下都生成相同的机器代码。 可能对MS的反馈将使他们对未来版本的警告不那么乏味。
我不知道这是否属实,但文章声称是明智和现实的。 for(;;)
类型比while(1)
更短
嗯。 您可能会发现K&R没有编写PDP-11编译器,因为PDP-11是一台“机器”(不是一种语言),它已经为自己的PDP-11指令集配备了自己的MACRO汇编程序。
K&R {据说’在…中编写了自己的’C’编译器..如果必须是MACRO就不会(因为那是PDP上唯一的指令集汇编程序)然后(据说)写了Unix在’C’中他们认为他们可以做得比DEC的PDP-11操作系统(RT-11和RSTS-11)更好……他们可能是对的!
for(;;)
是惯用的,所以如果您的代码只能由经验丰富的C程序员阅读,那就太棒了。 while(true)
对于没有经验的程序员和非C程序员来说会更容易理解。 前者还依赖于一些非显而易见的行为,即空布尔表达式的计算结果为true。 出于这个原因,如果你必须选择一个,我会说去后者。
但是我认为,在几乎所有实际情况中,程序员并不真正希望代码永远循环。 你总是有理由想要循环终止,即使只是用户已经命中了control-C。 永远不需要无限循环。