Мораль такова: писать программы, зависящие от очередности вычислений, - плохая практика, какой бы язык вы ни использовали. Естественно, надо знать, чего следует избегать, но если вы не знаете, как образуются побочные эффекты на разных машинах, то лучше и не рассчитывать выиграть на особенностях частной реализации.
Порядок, в котором выполняются вычисления, определяется инструкциями управления. Мы уже встречались с наиболее распространенными управляющими конструкциями такого рода в предыдущих примерах; здесь мы завершим их список и более точно определим рассмотренные ранее.
Выражение, скажем x = 0 , или i++ , или printf(:) , становится инструкцией , если в конце его поставить точку с запятой, например:
x = 0;
i++;
printf(…);
В Си точка с запятой является заключающим символом инструкции, а не разделителем, как в языке Паскаль.
Фигурные скобки {и }используются для объединения объявлений и инструкций в составную инструкцию , или блок , чтобы с точки зрения синтаксиса эта новая конструкция воспринималась как одна инструкция. Фигурные скобки, обрамляющие группу инструкций, образующих тело функции, - это один пример; второй пример - это скобки, объединяющие инструкции, помещенные после if, else, whileили for. (Переменные могут быть объявлены внутри любого блока, об этом разговор пойдет в главе 4.) После правой закрывающей фигурной скобки в конце блока точка с запятой не ставится.
Инструкция if-elseиспользуется для принятия решения. Формально ее синтаксисом является:
if ( выражение )
инструкция 1
else
инструкция 2
причем else-часть может и отсутствовать. Сначала вычисляется выражение, и, если оно истинно (т. е. отлично от нуля), выполняется инструкция 1 . Если выражение ложно (т. е. его значение равно нулю) и существует else-часть, то выполняется инструкция 2 .
Так как ifпросто проверяет числовое значение выражения, условие иногда можно записывать в сокращенном виде. Так, запись
if ( выражение )
короче, чем
if ( выражение != 0 )
Иногда такие сокращения естественны и ясны, в других случаях, наоборот, затрудняют понимание программы.
Отсутствие else-части в одной из вложенных друг в друга if-конструкций может привести к неоднозначному толкованию записи. Эту неоднозначность разрешают тем, что elseсвязывают с ближайшим if, у которого нет своего else. Например, в
if (n › 0)
if (а › b)
z = a;
else
z = b;
elseотносится к внутреннему if, что мы и показали с помощью отступов. Если нам требуется иная интерпретация, необходимо должным образом расставить фигурные скобки:
if (n › 0) {
if (а › b)
z = a;
}
else
z = b;
Ниже приводится пример ситуации, когда неоднозначность особенно опасна:
if (n ›= 0)
for (i=0; i ‹ n; i++)
if (s[i] › 0) {
printf(":");
return i;
}
else /* НЕВЕРНО */
printf("ошибка - отрицательное n\n");
С помощью отступов мы недвусмысленно показали, что нам нужно, однако компилятор не воспримет эту информацию и отнесет elseк внутреннему if. Искать такого рода ошибки особенно тяжело. Здесь уместен следующий совет: вложенные ifобрамляйте фигурными скобками. Кстати, обратите внимание на точку с запятой после z = a в
if (а › b)
z = а;
else
z = b;
Здесь она обязательна, поскольку по правилам грамматики за ifдолжна следовать инструкция, а выражение-инструкция вроде z = a; всегда заканчивается точкой с запятой.
Конструкция
if ( выражение )
инструкция
else if ( выражение )
инструкция
else if ( выражение )
инструкция
else if ( выражение )
инструкция
else
инструкция
встречается так часто, что о ней стоит поговорить особо. Приведенная последовательность инструкций if- самый общий способ описания многоступенчатого принятия решения. Выражения вычисляются по порядку; как только встречается выражение со значением "истина", выполняется соответствующая ему инструкция , на этом последовательность проверок завершается. Здесь под словом инструкция имеется в виду либо одна инструкция, либо группа инструкций в фигурных скобках.
Читать дальше