无限循环的"for(;;)"习语是否正确归因于 PDP-11 C 编译器?
Is "for(;;)" idiom for infinite loop correctly attributed to PDP-11 C compiler?
最近我发现了一篇文章,该文章声称在无限循环中选择for(;;)
而不是while(1)
的想法是因为PDP-11上最初可用的C编译器为while(1)
生成了额外的机器指令。
顺便说一句,现在甚至Visual c++的警告也倾向于前者。
对for(;;)
成语的这种归因有多现实?
在最初的K&R中明确提到了"for(;;)"习语。这对我来说就足够了
谨防某些"感性归因",因为往往是由于缺乏上下文而导致的假消息来源。OP将消息标记为C和c++。
现在,K&R可以是C历史的半神,但肯定不能被认为是c++的权威。此外,编译器优化可以在c++中发挥基本作用,但C系统程序员经常认为这是"滥用"(他们喜欢将C视为"带有表达式的汇编程序",而不是"高级语言")。
现在的编译器很可能会生成完全相同的代码(这很容易证明),使用其中一个或另一个更多的是品味问题,而不是其他。
在这个意义上,我倾向于for(;;)
,因为我可以很容易地把它读成"for-ever",而while(true)
读成"而这个真实的东西是真实的",让你弄清楚如果它甚至可能是假的... .浪费了2毫秒的大脑!(但这是我的个人意见:我知道很多人不得不考虑for(;;)
而不是while(true)
)
然而,我也能认出它们都是"图像表示"(不实际阅读文本,只是通过摄影记忆看看它们是什么样子),指向同一个智力概念(待在这里直到有人把你从里面踢出去)。
关于MS警告,有时它可以避免您编写错误的表达式(如true||a
)。但是显然被滥用了,不应该出现在里面没有操作的琐碎表达式中。在这两种情况下,MS编译器都会生成相同的机器码。也许给微软的反馈会让他们在未来的版本中对这个警告不那么乏味。
以下是V7 Unix编译器cc
生成的结果(使用SIMH和来自TUHS的图像):
$ cat>a.c
main(){
while(1);
}
$ cat>b.c
main(){
for(;;);
}
$ cc -S a.c
$ cc -S b.c
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
当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
所以for(;;)
在不使用优化的情况下编译到更少的指令是正确的。然而,当使用-O
编译时,两个程序产生的完全是相同的程序集:
.globl _main
.text
_main:
~~main:
jsr r5,csv
L4:jbr L4
.globl
.data
,当我添加一个printf("Hello");
的循环体时,程序仍然是一样的。
所以,这个习语可能起源于PDP-11机器语言,但到1979年,这种差异已经在很大程度上无关重要了。
我不知道这是不是真的,但是文章的说法是明智的和现实的。for(;;)
比while(1)
更短
我想你会发现K&R并没有编写PDP-11编译器,因为PDP-11是一个"机器"(而不是一种语言),它已经为自己的PDP-11指令集拥有了自己的MACRO汇编器。
K&R{据说)写了他们自己的'C'编译器…嗯. .如果它必须是宏,不是吗(因为这是PDP上唯一可用的指令集汇编器),然后(据说)用'C'编写Unix,因为他们认为他们可以比DEC的PDP-11操作系统(RT-11和RSTS-11)做得更好。他们可能是对的!
for(;;)
是惯用的,所以如果你的代码只有经验丰富的C程序员才能阅读,那就太好了。while(true)
对于没有经验的程序员和非C程序员来说更容易理解。前者还依赖于一些不明显的行为,即空布尔表达式的计算结果为true。基于这些原因,如果你必须选择一个,我会说选择后者。
然而我认为在几乎所有的实际情况下,程序员都不希望代码永远循环。希望循环终止总是有原因的,即使只是用户点击了control-C。不需要无限循环
- 将变量 B 和 C 的乘积归因于变量 A
- 将一个数组归因于另一个数组的困难
- 相当于旧版C++的 C++11 unordered_map
- G++ - 警告:扩展初始值设定项列表仅适用于 -std=C++11 或 -std=GNU++11
- 我如何归因于迭代器的另一个迭代
- 是否有任何 DirectX 11 (HLSL 5.0) 等效于 DirectX 9 纹理"string function"语法?
- C++11 何时相对于运算符优先级进行算术类型转换
- "new int[8]()"相当于C++11中的"new int[8]{}"吗?
- C++11:std::get<> 等效于 n 维数组
- C++11:用容器参数定义函数(类似于基于范围的)
- 来自prioric++11的std::vector::begin()是否等效于C++11中的std::vector::d
- 相当于Boost has_dereference的C++11 std
- 非本地C++11 lambdas是否存在于匿名命名空间中
- C++11 获取第一个(第二个等)参数的类型,类似于result_of
- C++11 相当于 Java 的实例是什么
- 什么是C++11等效于boost::date_time::not_a_date_time
- Qt Linux "QMAKE_CXXFLAGS += -std=c++11"等效于Windows?
- 无限循环的"for(;;)"习语是否正确归因于 PDP-11 C 编译器?
- 在索引和值"for i, v in enumerate(listVar):"上是否有 C++/C++11 类似于 python 迭代?
- c++11等效于c#联锁增量