“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 

acwhile )编译为:

 .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 

bcfor )变为:

 .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。 永远不需要无限循环。