2014-02-11 5 views
22

В C++ вам разрешено иметь пустое состояние внутри цикла for, например, как в for (;;) или for (int x = 0;; ++x). Но вы не можете сделать while().while цикл требует явного условия, для цикла нет, почему?

Если условие отсутствует в цикле for, условие считается true (поэтому петли на петлях навсегда). Почему это не так с while циклами, то есть, что за аргумент не позволяет while() быть псевдонимом while (true)?

+8

Ответ скорее всего 2 раза: 1) быть обратно совместимым с C99 и 2), потому что комитет по стандартам сказал это. Может быть какая-то грамматическая причина, почему 'while()' может не работать, но теоретически это могло быть исправлено, если они действительно этого хотели. –

+2

@ZacHowland 1) Тогда вопрос в том, почему это имеет место в C99;) – leemes

+2

@leemes - Потому что комитет по стандартам C90 сказал так;) –

ответ

30

Предположительно, это побочный эффект того факта, что каждое заданное предложение внутри оператора for является необязательным. Есть причины, по которым некоторые for-loops не нуждаются в задании; есть причины, по которым некоторые другие не нуждаются в состоянии; есть причины, по которым другим людям не понадобится приращение. Требование, чтобы их было минимальное количество, было бы ненужной сложностью.

+1

+1 для будучи очень легким для понимания способом. – Annabelle

+0

Это ответ на вопрос, почему 'for (;;)' является действительным, но не учитывает, почему 'while()' не может быть (вероятно, будет основан на мнениях). –

+1

Дело в том, что они не задавали условий, которые необязательно выполнялись в контрольных утверждениях в целом. Это было чисто вопросом согласованности в частном случае for-loop. – Sneftel

8

Следующая из книги Глубокие секреты C:

Раннее C не было отдельных операторов для & и & & или | и ||. (Получил это?) Вместо этого он использовал понятие (унаследованное от B и BCPL) «контекста истинности»: где ожидалось булево значение, после «if» и «while» и т. Д. & и | операторы были интерпретированы как & & и || есть сейчас; в обычных выражениях использовались побитовые интерпретации. Это получилось неплохо, но было трудно объяснить. (В контексте истинностного значения было понятие «операторов верхнего уровня».)

while() Таким образом, у вас есть он, while() будет устанавливать контекст для значения истинности и не может быть пустым или подразумеваться для по той же причине, если() не может быть пустым, механики раннего языка ожидали, что они не будут.

+3

Я не понимаю. Что означает смысл операторов и «контекст», связанные с вопросом, если выражение * optional *? – leemes

+0

Чтобы реализовать «истинный-значение-контекст» в C (как в B и BCPL), логическое значение ожидалось после if() и while() ... поэтому они не могут быть пустыми. Несмотря на то, что первоначальная причина (неопределенность значения & as & or && и т. Д.) Больше отсутствует, дизайн был передан в более новые версии C, а затем на C++. –

+3

По-прежнему не понимаю, почему это аргумент. Они могли бы сказать, что ** если ** есть что-то в круглых скобках, это булевой контекст выражения. Кроме того, почему то же самое не считается для циклов 'for'? – leemes

3

Я думаю, что основное различие между выражениями и заявлениями.

Конечно, в C два не строго различаются, но я бы сказал, что для петли:

for (statement; expression; statement) { 
    ... 
} 

Выражение представляет собой логическое выражение, в то время как заявления ... заявления, которые имеют сторону последствия. Конечно, C не является полуфункциональным; вы можете поместить побочные эффекты в среднее выражение, но это не идиоматично.

Но иногда вы не хотите выражения, но заявления в начале и в каждой итерации цикла полезно, так что среднее выражение не является обязательным:

// Infinite counter 
int i; 
for (i = 0;;i++) { 
    ... 
} 

Это по определению означает, что выражение считается всегда верно

с другой стороны, while и if может только принимает выражение. Там нет ничего очень полезно слева (в отличие от двух полезных утверждений слева), если опустить это выражение: никто не будет писать

// Idiot coding 
if (true) { 
    ... 
} 

потому что точка из if утверждения проверить, является ли какая-то неизвестная правда или нет!

То же самое с while. Точка while должна делать что-то снова и снова, пока условие в виде выражения истинно. Это похоже на «итерированный if». Вот почему

while() { 
    ... 
} 

не считается логическим и, следовательно, не допускается.

-3

Разница между логическими утверждениями, используемыми в то время как() и (;;) петлей является то, что:

  • в случае для утверждения определяет состояние из выхода из цикла

  • в случае время() оператор определяет условие выполнения цикла

Предполагая, что вы видите, что для ввода цикла вам нужно хотя бы условие выполнения, а не условие выхода.

+2

Синтаксис 'for' loop содержит условие для выполнения цикла, точно так же, как синтаксис цикла while в – anatolyg

1

В соответствии с Document:

6.8.5.3 для постановки

for (clause-1 ; expression-2 ; expression-3) Изложение утверждение ведет себя следующим образом:

  1. Выражение выражение-2 является контролирующим выражение, которое равно , оценивается перед каждым исполнением тела цикла. Выражение выражение-3 оценивается как выражение void после каждого выполнения тела цикла. Если предложение-1 является объявлением, область любых объявляемых объявлением - это остальная часть декларации и полный цикл , включая два других выражения; в достигается порядок выполнения перед первой оценкой управляющего выражения . Если предложение-1 является выражением, оно оценивается как выражение void перед первой оценкой контрольного выражения .158)
  2. Оба предложения-1 и выражение-3 могут быть опущены. Выведенное значение выражение-2 заменено на ненулевую константу.

Таким образом, в случае for цикла, условие будет заменено ненулевой константой и без такой реализации для while цикла.

+0

@downvoters, пожалуйста, укажите некоторые комментарии ... –

+0

OP хотел узнать причины этого текста из Стандарта; Я предполагаю, что он уже знает синтаксис C/C++ – anatolyg

+0

«Пропущенное выражение-2 заменяется ненулевой константой». ?? !!! –

8

В C++ вам разрешено иметь пустое состояние внутри для цикла ... что аргумент за не давая while() быть псевдонимом while(true)?

Прежде всего, C++ (и C# и многие другие языки) являются способом обратной совместимости с C, поэтому давайте поговорим о C.

Давайте сделаем некоторые заявления и сделаем вывод.

  1. Существует веская причина, по которой цикл for позволяет опустить условие.
  2. То же самое относится к петле while.
  3. Цикл while не позволяет опустить условие; это непоследовательно.
  4. Согласованность выбора дизайна в разных операторах является важным фактором при разработке C.
  5. Следовательно, должна быть неочевидная веская причина несогласованности; должна быть веская причина, почему петля while не соответствует петле for.

И теперь возникает вопрос: «Какая эта неочевидная веская причина?»

Но вопрос имеет смысл только в том случае, если цепь логики, описанная выше, является правильной, а это не так. Из этих утверждений фактически верно только # 3! Цикл for в C - плохой дизайн; он лишний, запутанный для новичков, и его лексические соглашения несовместимы с остальной частью языка. Он обеспечивает почти нулевую дополнительную репрезентативную мощность для языка над простым циклом while.

На ваш вопрос нет ответа; правильный ответ скорее полностью отвергает предпосылку вопроса. Цикл for кажется разумным, потому что это 40-летняя неудача, с которой большинство из нас выросло, поэтому его причуды - вторая природа; это знакомство, а не хороший дизайн. Если бы мы выросли без цикла for, мы бы не добавляли его.

+1

И все же недавно добавлены диапазоны for-loops *, указывающие на отличный аппетит для цикла, предназначенного для выражения итерации по последовательности. Его семантика может быть немного волосатой, но я думаю, что это скорее вопрос ограничений способности C к абстрактным последовательностям, чем целесообразность включения этой функции в целом. – Sneftel

+1

@Sneftel: О, не пойми меня неправильно; Мне нравится идея цикла, который абстрагируется от операции повторения последовательности. Основная проблема с циклом 'for' заключается в том, что его синтаксис * настолько тупой *. Точку с запятой можно логически рассматривать как * последовательный состав оператора побочных эффектов *. Когда вы говорите 'A(); В(); C(); 'в C, что означает последовательно составлять побочные эффекты трех вызовов функций. Это то, что это означает везде, кроме цикла foreach, где это означает что-то совсем другое. –

+0

Это хороший момент. Было бы интересно, если бы они сделали синтаксис 'for (a) (b) (c) {...}' или даже 'для {a} {c} (b) {...}'. В конце концов, 'a' и' c', в некотором смысле, заслуживают быть блоками, а 'b' заслуживает того, чтобы этого не было. – Sneftel

Смежные вопросы