logo
Харви Дейтел, Пол Дейтел Как программировать на С++ / 02-Deitel-Стр-115-214

Глава 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 останется неизменным, что, вероятно, вызовет ло­гическую ошибку выполнения. К сожалению, мы не знаем простого приема, который мог бы помочь вам в решении этой проблемы!