
Рис. 5.4. Одна итерация цикла
Во-вторых, в чем преимущества такого подхода? Программа становится компактной. Но более важно то, что при этом объединяются в одном месте два процесса, которые управляют циклом. Первичным процессом является проверка того, продолжать ли выполнение цикла? В данном случае проверка заключается в выяснении, меньше ли значение переменной size, чем 18.5. Вторичный процесс изменяет значение проверяемого объекта; в данном случае размер обуви увеличивается на единицу.
Предположим, что вы забыли изменить размер обуви. Тогда значение переменной shoe всегда будет меньше 18.5, и цикл никогда не завершится. Вошедший в бесконечный цикл компьютер будет выводить одну и ту же строку. В конце концов, вы потеряете интерес к выводу и будете вынуждены как-то прервать выполнение программы. Проверка условия и изменение параметра цикла в одном месте, а не в разных, помогает помнить о необходимости изменить значение параметра цикла.
Недостаток объединения двух операций в одно выражение заключается в том, что это затрудняет понимание кода и увеличивает вероятность внесения ошибок.
Еще одно достоинство операции инкремента состоит в том, что она приводит к генерации несколько более эффективного кода на машинном языке по причине своего подобия действительным инструкциям машинного языка. Тем не менее, по мере улучшения компиляторов С поставщиками программного обеспечения это преимущество постепенно исчезает. Интеллектуальный компилятор способен распознать, что операцию х = х + 1 можно трактовать как ++х.
Наконец, эти операции обладают дополнительной характеристикой, которая может оказаться полезной в ряде тонких ситуаций. Чтобы выяснить, о чем идет речь, попробуйте запустить программу из листинга 5.11.
Операции, выражения и операторы 175
Листинг 5.11. Программа post_pre.c

Если все было сделано правильно, должен получиться следующий результат:
a a_post b pre_b
2 12 2
Как и было задумано, значения переменных а и b увеличились на единицу. Однако a post содержит значение переменной а перед изменением, а b prе — значение переменной b после изменения. Именно в этом заключается отличие между префиксной и постфиксной формами операции инкремента (рис. 5.5):
a_post = а++; // постфиксная форма: переменная а меняется после
// использования ее значения
b_pre= ++b; // префиксная форма: переменная b меняется до использования
// ее значения
Когда одна из этих операций инкремента применяется сама по себе, как в одиночном операторе едо++;, ее форма не имеет значения. Однако выбранная форма играет роль, если операция и ее операнд являются частью более крупного выражения, как в только что показанных операторах присваивания. В ситуациях подобного рода нужно иметь четкое представление о том, какой результат вы желаете получить. В качестве примера вспомните, что мы намеревались использовать следующую конструкцию:
while (++shoe < 18.5)
Такая проверка условия завершения цикла позволяет получить таблицу значений вплоть до размера 18. Если вы укажете shoe++ вместо ++shoe, то таблица расширится до размера 19, т.к. значение shoe будет увеличиваться после сравнения, а не до него.
Конечно, вы могли бы возвратиться к менее элегантной форме:
shoe = shoe + 1;
но тогда никто не поверит, что вы настоящий программист на языке С.
При чтении этой книги вы должны уделять особое внимание примерам применения операции инкремента. Задайте себе вопрос, использовали вы префиксную и постфиксную формы взаимозаменяемо или же обстоятельства диктовали конкретный выбор. Возможно, более разумная политика предполагает отказ от кода, в котором есть разница, какая форма выбрана — префиксная или постфиксная. Например, вместо
b = ++i; // если используется i++, значение переменной b будет другим
применяйте
++i; // строка 1
b = i; // переменная b получит то же значение, даже если в строке 1 указать i++
176 Глава 5

Рис. 5.5. Префиксная и постфиксная формы инкремента
Тем не менее, иногда интересно проявить некоторую беспечность, так что в данной книге не всегда соблюдается этот благоразумный совет.
Читать дальше