В C / C ++ почему делает do while (выражение); нужна точка с запятой? - PullRequest
35 голосов
/ 03 июня 2009

Полагаю, это облегчает анализ, но я не могу точно понять, почему.

Так, что это имеет ...

do
{
  some stuff
}
while(test);

more stuff

это лучше чем ...

do
{
  some stuff
}
while(test)

more stuff

Ответы [ 8 ]

57 голосов
/ 03 июня 2009

Потому что вы заканчиваете утверждение. Оператор заканчивается либо блоком (разделенным фигурными скобками), либо точкой с запятой. «делать это, пока это» является одним оператором и не может заканчиваться блоком (потому что он заканчивается «пока»), поэтому ему нужна точка с запятой, как и любой другой оператор.

30 голосов
/ 25 октября 2009

Если вы посмотрите на грамматику C ++, вы увидите, что операторы итерации определены как

while ( условие ) оператор

для ( для условия оператора init -opt ; выражение -opt ) заявление

do оператор while ( выражение );

Обратите внимание, что только оператор do-while имеет ; в конце. Итак, вопрос в том, почему do-while так отличается от остальных, что ему нужно это дополнительное ;.

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

Однако на практике это будет означать, что, например, следующий код

do
{
  /* whatever */
} while (i + 2) * j > 0;

в то время как действительный с точки зрения грамматики, действительно будет проанализирован как

do
{
  /* whatever */
} while (i + 2)

*j > 0;

Это формально звучит, но не совсем интуитивно. Я предполагаю, что по этим причинам было решено добавить более явный терминатор к выражению do-while - точку с запятой. Конечно, в ответе @Joe White есть также соображения о простой и простой последовательности: все обычные (не составные) операторы в C заканчиваются на ;.

24 голосов
/ 03 июня 2009

Это потому, что операторы while действительны в цикле do-while.

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

int x = 10;
int y = 10;

do 
  while(x > 0)
    x--;
while(x = y--);
9 голосов
/ 03 июня 2009

Хотя я не знаю ответа, последовательность кажется лучшим аргументом. Каждая группа операторов в C / C ++ завершается либо

  1. точка с запятой
  2. скоба

Зачем создавать конструкцию, которая ничего не делает?

6 голосов
/ 13 апреля 2011

Согласованность операторов управления потоком

Учитывая последовательность ...

if (expr) statement;
do statement; while (expr);
for (expr; expr; expr) statement;
while (expr) statement;

... все эти конструкции управления потоком заканчиваются точкой с запятой.

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

if (expr) { ... }
do { ... } while (expr);
for (expr; expr; expr) { }
while (expr) { }

Итак, у нас есть ';' или '}', но никогда не "голый" ')'.

Согласованность разделителей операторов

Мы можем, по крайней мере, сказать, что каждое утверждение должно быть ограничено ; или }, и визуально это помогает нам различать утверждения.

Если точка с запятой не требуется, рассмотрите:

do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4;

Очень трудно визуально разрешить это для различных утверждений:

do statement1; while (expr1)
statement2;
do ; while (expr2)
statement3;
while (expr3) statement4;

В отличие от этого, следующее легче разрешается как ; сразу после того, как условие while говорит вам искать в обратном направлении для do, и следующее утверждение не связано с этим while:

do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4;

Имеет ли значение, если люди делают отступ в своем коде, чтобы сделать поток понятным? Да, потому что:

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

Последствия использования препроцессора

Стоит также отметить известную идиому do-while препроцессора:

#define F(X) do { fn(X); } while (false)

Это можно заменить следующим образом:

if (expr)
    F(x);
else
    x = 10;

... дает ...

if (expr)
    do ( fn(x); } while (false);
else
    x = 10;

Если точка с запятой не является частью оператора do while, то оператор if будет интерпретироваться как:

if (expr)
    do-while-statement
; // empty statement
else
    x = 10;

... и, поскольку после if есть два оператора, он считается завершенным, что делает оператор else бесподобным.

3 голосов
/ 03 июня 2009

C заканчивается точкой с запятой (тогда как Pascal разделен точкой с запятой). Было бы непоследовательным опускать точку с запятой там.

Честно говоря, я ненавижу повторное использование while для цикла do. Думаю повторить - пока не стало бы менее запутанным. Но это то, что есть.

1 голос
/ 24 сентября 2011

Мой ответ таков: у компилятора может возникнуть путаница, если мы не добавили точку с запятой в завершение цикла do.....while();. Без этого не понятно про:

  1. когда заканчивается?
  2. Если while может следовать за отдельным циклом сразу после цикла do.

Вот почему мы включаем точку с запятой в конце цикла do......while, чтобы указать, что цикл завершается здесь, если условие ложно.

1 голос
/ 03 июня 2009

В C / C ++ пробелы не вносят вклад в структуру (например, в python). В операторах C / C ++ должен заканчиваться точкой с запятой. Это разрешено:

do
{
  some stuff; more stuff; even more stuff;
}
while(test);
...