Является ли "for (;;)" идиома для бесконечного цикла правильно отнесена к компилятору PDP-11 C?

Недавно я нашел эту статью, в которой утверждается, что идея предпочитать for(;;) над while(1) для бесконечного цикла появилась потому, что компилятор C изначально доступный на PDP-11, генерировал дополнительную машинную команду для while(1).

Btw теперь даже предупреждения Visual С++ предпочитают прежние.

Насколько реалистична такая атрибуция for(;;) идиомы?

Ответ 1

Здесь, что производит компилятор 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 году разница уже была в значительной степени неактуальной.

Ответ 2

Идиома "for (;;)" явно упоминается в исходном K & R. Эта атрибуция достаточно для меня:)

Ответ 3

Остерегайтесь определенной "разумной атрибуции", потому что они часто являются источниками ложных мифов из-за отсутствия контекста. OP отметил сообщение как C, так и С++.

Теперь K & R может быть полубогами относительно истории C, но, конечно, не может считаться авторитетом в С++. Более того, оптимизация компилятора может играть фундаментальную роль в С++, но часто рассматривается как "оскорбительная" из системных программистов C (им нравится видеть C как "Ассемблер с выражениями", а не "язык высокого уровня" ).

Сегодняшние компиляторы будут давать гораздо более точно один и тот же код (это может быть легко доказано), а использование того или другого гораздо более важно, чем другое.

В этом смысле я предпочитаю for(;;), потому что я могу легко прочитать его как "вечно", а while(true) читать как "пока эта истина верна", заставляя вас понять, как это может быть быть ложным.... 2 мс мозга потрачены впустую! (Но это личное мнение: я знаю многих людей, которые больше думают о for(;;), чем while(true))

Однако я также могу распознать их как "изобразительное представление" (фактически не прочитав текст, просто глядя, как они выглядят через фотографическую память), указывая на одну и ту же интеллектуальную концепцию (оставайтесь здесь, пока кто-то не ударит вас с внутри).

О предупреждении MS, когда-нибудь это избавит вас от плохо написанных выражений (например, true||a). Но явно злоупотребляют и не должны появляться для тривиальных выражений без операции внутри. Nerveless, MS компилятор производят один и тот же машинный код в обоих случаях. Может быть, обратная связь с MS сделает их менее утомительными в отношении этого предупреждения в будущих выпусках.

Ответ 4

Я не знаю, правда ли это, но требование статьи разумно и реалистично. А for(;;) короче, чем while(1)

Ответ 5

Um. Подумайте, вы обнаружите, что K & R не записывал компилятор PDP-11, поскольку PDP-11 был "машиной" (а не языком), у которой уже был свой собственный MACRO Assembler для собственного набора команд PDP-11.

K & R (по общему мнению) написал свой собственный компилятор 'C' в... ну.. если бы это был MACRO, не было бы (поскольку это был единственный набор Assembler, доступный на PDP), а затем (по общему мнению) написал Unix в "C", поскольку они думали, что они могут сделать лучше, чем DEC PDP-11 Operating Systems (RT-11 и RSTS-11).. и они, вероятно, были правы!

Ответ 6

for(;;) является идиоматичным, поэтому отлично, если ваш код будет когда-либо прочитан опытными программистами C. while(true) будет более понятным для неопытных программистов и программистов, не относящихся к C. Первый также полагается на некоторое неявное поведение, а именно, что пустое булевское выражение оценивается как true. По этой причине, если вы должны выбрать один, я бы сказал, идите за последним.

Однако Я бы сказал, что практически во всех реальных случаях программист действительно не хочет, чтобы код зацикливался навсегда. Всегда есть причина, по которой вам может понадобиться завершить цикл, даже если он просто ударил элемент управления-C. Никогда не требуется бесконечный цикл.