Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
b = ++i; // если используется i++, значение переменной b будет другим
применяйте
++i; // строка 1
b = i; // переменная b получит то же значение, даже если в строке 1 указать i++
176 Глава 5
Рис. 5.5. Префиксная и постфиксная формы инкремента
Тем не менее, иногда интересно проявить некоторую беспечность, так что в данной книге не всегда соблюдается этот благоразумный совет.
декрементирование: —
Для каждой формы операции инкремента имеется соответствующая форма операции декремента. Вместо ++ указывайте —:
--count; // префиксная форма операции декремента count--; // постфиксная форма операции декремента
Листинг 5.12 служит иллюстрацией того, что компьютер может быть опытным поэтом.
Листинг 5.12. Программа bottles. с
Вывод начинается примерно так:
100 бутылок родниковой воды на полке, 100 бутылок родниковой воды! Возьмите одну из них и пустите по кругу,
99 бутылок минеральной воды!
99 бутылок родниковой воды на полке, 99 бутылок родниковой воды! Возьмите одну из них и пустите по кругу,
98 бутылок родниковой воды!
Все это продолжается некоторое время и закачивается следующим образом:
1 бутылок родниковой воды на полке, 1 бутылок родниковой воды!
Возьмите одну из них и пустите по кругу,
0 бутылок родниковой воды!
Операции, выражения и операторы 177
Очевидно, что у опытного поэта есть проблема с множественным числом, но это можно исправить за счет использования условной операции, описанной в главе 7.
Кстати, операция > означает “больше чем”. Как и < (“меньше чем”), она является операцией оттаения. Более подробно операции отношений рассматриваются в главе 6.
Приоритеты операций
Операции инкремента и декремента имеют очень высокий приоритет; выше по приоритету только скобки. Поэтому х*у++ означает (х) * (у++), но не (х*у)++, что благоприятно, т.к. последняя конструкция не имеет смысла. Операции инкремента и декремента применяются только к переменным (или, в общем случае, к модифицируемым 1-значепиям), а само произведение х*у не является модифицируемым 1-значением, хотя его части таковыми являются.
Не путайте приоритеты этих двух операций с порядком их вычисления. Предположим, мы имеем такой код:
у = 2;
n = 3;
nextnum = {у + n++) * 6;
Какое значение получит nextnum? Подстановка значений дает следующее:
nextnum = (2 + 3)*6 = 5*6 = 30
Значение переменной n увеличивается до 4 только после ее использования. Приоритет операции говорит о том, что операция ++ применяется только к n, но не к у + n. Он также указывает, когда значение n используется для вычисления выражения, но момент изменения значения n определяется природой операции инкремента.
Когда n++ является частью выражения, можно считать, что это означает “использовать переменную n, а затем увеличить ее значение на единицу”. С другой стороны, ++п означает “увеличить значение переменной n на единицу, а затем использовать ее”.
Не умничайте
Слишком частое применение операции инкремента быстро приводит к путанице. Например, может показаться, что программу для вывода целых чисел и их квадратов squares.с (листинг 5.4) удастся улучшить, заменив в ней цикл while таким циклом:
while (num < 21)
{
printf("%10d %10d\n", num, num*num++);
}
Код выглядит вполне разумно. Вы выводите число num, умножаете его само на себя, чтобы получить квадрат, а затем увеличиваете значение num на 1. Действительно, эта программа может даже работать в некоторых системах, правда, не во всех. Проблема заключается в том, что когда функция printf() собирается извлекать значения для вывода, она может сначала вычислить последний аргумент, увеличив значение num на 1, и только затем перейти к следующему аргументу.
В результате вместо того, чтобы вывести
5 25 она может вывести
6 25
178 глава 5
Она даже может работать справа налево, используя 5 в качестве значения крайнего правого аргумента num и 6 в качестве значения следующих двух аргументов, приводя к такому выводу:
6 30
Компилятор языка С может самостоятельно решать, какой аргумент функции вычислять первым. Такая свобода выбора увеличивает эффективность компилятора, но может стать причиной проблем, если операция инкремента применяется к аргументу функции. Другим возможным источником неприятностей может стать оператор следующего вида:
ans = num/2 + 5*(1 + num+ + );
И снова проблема заключается в том, что компилятор может выполнять действия не в том порядке, который вы имели в виду. Вы могли предполагать, что сначала будет вычислено выражение num/2 и только затем произойдет переход к вычислению другой части выражения, однако компилятор вполне может первым вычислить последний элемент, увеличить значение num и использовать это новое значение для вычисления num/2. Здесь не существует никаких гарантий.
Еще одним источником проблем может стать такая конструкция:
n = 3;
у = n++ + n++;
Действительно, после выполнения второго оператора значение n увеличивается на 2, но значение у будет неопределенным. Компилятор может применить старое значение n дважды при вычислении значения у, а затем дважды увеличить значение п на единицу. При этом у принимает значение 6, a n значение 5, либо он может использовать старое значение один раз, увеличить значение n один раз, задействовать это значение во втором экземпляре n в выражении, а затем инкрементировать n во второй раз. В таком случае у принимает значение 7, а n — значение 5. Возможен как первый, так и второй вариант. Точнее говоря, результат не определен, т.е. стандарт С не регламентирует, каким должен быть результат.
Описанных выше проблем легко избежать, если руководствоваться следующими рекомендациями.
• Не применяйте операцию инкремента или декремента к переменной, которая является частью более чем одного аргумента функции.
• Не используйте операцию инкремента или декремента с переменной, которая появляется в выражении более одного раза.
С другой стороны, в языке С имеются определенные гарантии относительно того, когда выполняется инкрементирование. Мы вернемся к этой теме, когда будем рассматривать точки следования в разделе “Побочные эффекты и точки следования” далее в главе.
Выражения и операторы
Мы применяли термины выражение и оператор на протяжении нескольких начальных глав, а теперь настало время подробнее рассмотреть их смысл. Операторы формируют базовые таги программы на С, и большинство операторов построено на основе выражений. Отсюда следует, что в первую очередь необходимо подробно изучить выражения.
Читать дальшеИнтервал:
Закладка: