"for(;;)"无限循环的习惯用法是否正确归因于PDP-11 C编译器?

sha*_*oth 10 c c++ compiler-construction history pdp-11

最近我发现这篇文章声称偏爱无限循环的想法来for(;;)while(1),因为最初在PDP-11上可用的C编译器生成了额外的机器指令while(1).

顺便说一下,即使Visual C++警告也倾向于前者.

这种for(;;)成语的归属有多现实?

pau*_*sm4 9

原来的K&R中明确提到了"for(;;)"成语.这对我来说足够了:)

  • 请记住,K&R编写了PDP-11编译器,这是导致该书的工作原型...... (2认同)
  • 它明确提到`for(;;)`,但不是PDP-11或任何有关生成代码的内容.它只是说如果省略条件,它总是被认为是真的. (2认同)

Emi*_*lia 7

要注意某些"明智的归属",因为缺乏背景,往往是虚假的秘密.OP标记了C和C++的消息.

现在,K&R可能是关于C历史的半神,但肯定不能被认为是C++的权威.此外,编译器优化可以在C++中发挥基础作用,但通常被C系统程序员视为"滥用"(他们喜欢将C视为"带表达式的汇编程序",而不是"高级语言").

今天的编译器很可能会生成完全相同的代码(这可以很容易地证明),而使用其中一个或更多的东西更多的是品味问题,然后是其他问题.

在这个意义上,我倾向于赞成,for(;;)因为我可以轻松地将其视为" 永远 ",而while(true)读作" 虽然这是真的是真的 ",让你想象如果它甚至可能是假的....... 2毫秒的脑子浪费了!(但它是一个个人观点:我知道有不少人更多地考虑for(;;)while(true))

然而,我也可以认出它们都是"图形表示​​"(没有实际阅读文本,只是通过摄影记忆看它们看起来如何通过照相记忆)指向同一个知识概念(留在这里直到有人会把你从内部踢开).

关于MS警告,有时可以避免使用写得不好的表达式(例如true||a).但是对于没有操作的琐碎表达式,显然是被滥用,并且不应该出现.Nerveless,MS编译器在两种情况下都生成相同的机器代码.可能对MS的反馈将使他们对未来版本的警告不那么乏味.

  • 你可以非常酷,并添加`#define ever(;;)`.然后你可以写字面`永远`. (9认同)
  • 只是`#define forever`并让它在`奇怪的周上为';;;'和在偶数时为`while(1)`. (7认同)
  • 当然,我在开玩笑.任何理智的C程序员都会写`#define EVER(;;)`,但`for EVER`看起来并不那么好[再次开玩笑]. (4认同)

Fre*_*Foo 6

这是V7 Unix编译器cc生成的内容(使用SIMH和来自TUHS的图像):

$ cat>a.c
main(){
 while(1);
}
$ cat>b.c
main(){
 for(;;);
}
$ cc -S a.c
$ cc -S b.c
Run Code Online (Sandbox Code Playgroud)

a.c(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
Run Code Online (Sandbox Code Playgroud)

b.c(for)变为:

.globl  _main
.text
_main:
~~main:
jsr     r5,csv
jbr     L1
L2:L4:jbr       L4
L5:L3:jmp       cret
L1:jbr  L2
.globl
.data
Run Code Online (Sandbox Code Playgroud)

因此,在for(;;)不使用优化时编译为更少的指令至少是正确的.但是,在编译时-O,两个程序生成完全相同的程序集:

.globl  _main
.text
_main:
~~main:
jsr     r5,csv
L4:jbr  L4
.globl
.data
Run Code Online (Sandbox Code Playgroud)

当我添加循环体时printf("Hello");,程序仍然是相同的.

因此,成语可能源于PDP-11机器语言,但到了1979年,差异已经基本上无关紧要了.