Отсутствие условия цикла в цикле for и while

while(cond) // fine
for(;cond;) //fine

но когда я снимаю условную часть

while() //syntax compilation error 
for(;;) //Infinite loop

Как эти циклы реализованы внутри? Или как компилятор (парсер) узнает, что пустое условие в while это ошибка и в for как бесконечность?

Я не нашел ничего об этом особенно, я думаю, что такие парни как я (которые являются новичками) в C, могли бы иметь ту же путаницу

5 ответов

Решение

Стандарт требует, чтобы пропущенное условие для for цикл заменяется ненулевой константой:

От C11 6.8.5.3: (выделено мое)

6.8.5.3 для заявления

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

2 И пункт-1, и выражение-3 могут быть опущены. Пропущенное выражение-2 заменяется ненулевой константой.

Так как нет такого требования для while цикл (если условие опущено), я полагаю, он оставлен для реализации компилятора.

Нет технической причины, объясняющей, почему один работает, а другой нет. Это человеческий фактор рассмотрения языковых дизайнеров. Они чувствовали, что бесконечный цикл с использованием for (;;) имеет больше смысла, чем while (), На них, возможно, повлиял ALGOL, язык, используемый пещерными людьми.

... как компилятор (парсер) узнает, что пустое условие в то время как ошибка и в качестве бесконечного?

Потому что определение языка определяет его как в синтаксисе (грамматике), так и в семантике.

Вот синтаксис для while цикл:

while ( expression ) statement

и вот синтаксис для for петля (по состоянию на C2011):

for ( expressionopt ; expressionopt ; expressionopt ) statement
for ( declaration expressionopt ; expressionopt ) statement

Индекс выбора в каждом expressionopt в for оператор указывает, что соответствующее выражение не является обязательным. Это подтверждается текстом:

6.8.5.3 для заявления

...
2 И пункт-1, и выражение-3 могут быть опущены. Пропущенное выражение-2 заменяется ненулевой константой.

Напротив, контролирующее выражение while Оператор не помечен как необязательный, что также подчеркивается в тексте:

6.8.5.1. Оператор while

1 Оценка управляющего выражения выполняется перед каждым выполнением тела цикла.

Не так много места, чтобы интерпретировать, что управляющее выражение может быть опущено.

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

Это часть синтаксиса Си. Каждый язык программирования имеет свою формальную грамматическую спецификацию (здесь это C формальная грамматика в BNF - то есть, что синтаксически правильно, а что нет. В C формальной грамматике вы можете видеть, что while должно выглядеть так:

'while' '(' exp ')' stat

Слова / символы в одинарных кавычках (терминальные символы) обязательны: 'while', '(' и ')'. Слова без кавычек (нетерминальные символы) - это то, что также указано в формальной грамматике. Если бы вы проанализировали формальную грамматику C, вы бы увидели, что там exp не может быть ничем. С другой стороны, если вы посмотрите на это, вы увидите, что это может выглядеть так:

'for' '(' exp ';' exp ';' exp ')' stat

| 'for' '(' exp ';' exp ';' ')' stat

| 'for' '(' exp ';' ';' exp ')' stat

| 'for' '(' exp ';' ';' ')' stat

| 'for' '(' ';' exp ';' exp ')' stat

| 'for' '(' ';' exp ';' ')' stat

| 'for' '(' ';' ';' exp ')' stat

| 'for' '(' ';' ';' ')' stat

(| означает ИЛИ).

Когда вы компилируете программу, лексический анализатор (часть компилятора) проверяет, является ли ваш код синтаксически правильным (т.е. соответствует формальной грамматике) и в зависимости от исходного кода выполняет другие действия.

Другие вопросы по тегам