Глава 2
Операция | Ассоциативность | Тип операций |
О | слева направо | круглые скобки |
+ — + ! (тип) | справа налево | унарные |
* / % | слева направо | мультипликативные |
+ | слева направо | аддитивные |
« » | слева направо | поместить в/взять из |
< <= > >= | слева направо | отношение |
! = | слева направо | проверка на равенство |
&& | слева направо | логическое И |
I I | слева направо | логическое ИЛИ |
? : | справа налево | условная |
+= -= *= /= %= | справа налево | присваивание |
/ | слева направо | запятая (последование) |
Рис. 2.31. Приоритеты и ассоциативность операций
В С++ существуют два обстоятельства, создающих подобные проблемы. Одно из них заключается в том, что любое выражение, имеющее некоторое значение, может использоваться в решающей части любой управляющей структуры. Если значение выражения равно 0, оно трактуется как false, если же значение не равно 0, оно трактуется как true. Второе обстоятельство связано с тем, что в С++ присваивание, как уже говорилось, имеет значение, а именно — то значение, которое присваивается переменной, расположенной слева от операции присваивания. Например, предположим, что мы намерены написать
if (payCode == 4)
cout « "Вы получили премию!" « endl;
но случайно написали
if (payCode = 4)
cout « "Вы получили премию!" « endl;
Первый оператор if должным образом присуждает премию тому, чей pay-Code равен 4. Второй оператор if (ошибочный) оценивает значение операции присваивания в условии if постоянным значением 4. Поскольку любое ненулевое значение интерпретируется как true, условие в данном операторе if всегда истинно, и премии будут получать все, независимо от действительной величины payCode! Более того, переменная payCode будет изменена, хотя предполагается, что она должна только проверяться!
Типичная ошибка программирования 2.22
Использование операции == для присваивания или операции = для проверки равенства.
Обычно программисты записывают подобные условия как x == 7, т.е. помещают имя переменной слева, а константу — справа. Если переставить их так, чтобы константа была слева, а имя переменной справа, т.е. записать
Управляющие структуры 141
7 == x, то программист, по ошибке заменивший операцию == операцией =, будет защищен компилятором. Компилятор воспримет такую ошибочную подмену как синтаксическую ошибку, так как слева в операторе присваивания может стоять только имя переменной. Это во всяком случае защитит от крайне неприятной логической ошибки во время выполнения.
Имена переменных относятся к так называемым Ь-величинам (lvalue — левая величина, левое значение), которые могут использоваться слева от операции присваивания. Константы относятся к так называемым Н-величинам (rvalue — правая величина, правое значение), которые могут использоваться только справа от операции присваивания. Отметим, что Ь-величины могут использоваться как К-величины, но не наоборот.
Хороший стиль программирования 2.29
Если выражение проверки равенства содержит переменную и константу, например, x == 1, некоторые программисты предпочитают записывать подобные выражения, помещая константу слева, а имя переменной справа, чтобы предохранить себя от логической ошибки при случайной подмене операции == операцией =.
Противоположная ошибка может быть столь же неприятной. Предположим, программист хотел присвоить значение переменной простым оператором типа
x = 1;
но случайно написал
X == 1;
Это тоже не является синтаксической ошибкой. Компилятор просто расценит это как условное выражение. Если x равно 1, это условие истинно и выражение возвращает значение 1. Если x не равно 1, условие ложно и выражение возвращает значение 0. Независимо от того, какое значение возвращается, операция присваивания отсутствует, так что это значение просто потеряется и значение x останется неизменным, что, вероятно, вызовет логическую ошибку выполнения. К сожалению, мы не знаем простого приема, который мог бы помочь вам в решении этой проблемы!
- 116 Глава 2
- 2.13. Основы повторения, управляемого счетчиком
- 2.14. Структура повторения for (цикл)
- 120 Глава 2
- 122 Глава 2
- 2.15. Пример использования структуры for
- 124 Глава 2
- 126 Глава 2
- 2.16. Структура множественного выбора switch
- Глава 2
- 130 Глава 2
- 132 Глава 2
- 2.17. Структура повторения do/while
- 134 Глава 2
- 2.18. Операторы break и continue
- Глава 2
- 2.19. Логические операции
- 138 Глава 2
- Глава 2
- 2.21. Заключение по структурному программированию
- IfcrpyKTypa (единственный выбор)
- Глава 2
- Глава 2
- 148 Глава 2
- Глава 2
- Глава 2
- Глава 2
- 156 Глава 2
- 158 Глава 2
- 160 Глава 2
- 2.1. А) следование, выбор и повторение, b) if/else. С) управляемым счет чиком или определенным заранее, d) Метку, сигнал, флаг или лож ный сигнал.
- 162 Глава 2
- 164 Глава 2
- 166 Глава 2
- 168 Глава 2
- 170 Глава 2
- 172 Глава 2
- 174 Глава 2
- 176 Глава 2
- 178 Глава 3
- Глава 3
- 3.3. Математические библиотечные функции
- 3.4. Функции
- Глава 3
- 3.5 Определения функций
- 184 Глава 3
- 186 ГлаваЗ
- 3.6. Прототипы функций
- 188 Глава 3
- 3.7. Заголовочные файлы
- 3.8. Генерация случайных чисел
- Глава 3
- 192 Глава 3
- 194 Глава 3
- 3.9. Пример: азартная игра
- Глава 3
- 198 Глава 3
- 3.10. Классы памяти
- 200 Глава 3
- 3.11. Правила, определяющие область действия
- 202 Глава 3
- 204 Глава 3
- 3.12 Рекурсия
- Глава 3
- 6) Значения, возвращаемые после каждого рекурсивного вызова
- 3.13. Пример использования рекурсии: последовательность чисел Фибоначчи
- Глава 3
- 3.14. Рекурсии или итерации
- 212 Глава 3
- Глава 3
- Глава 4
- Глава 5
- Глава 6
- 3.15. Функции с пустыми списками параметров
- 214 Глава 3
- 3.16. Встраиваемые функции