Согласованность операторов управления потоком
Учитывая последовательность ...
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
бесподобным.