Привет ! |
Выражения и операторы
3.2 Сводка операций
Здесь приводится краткая сводка операций и несколько примеров. Каждая операция сопровождается одним или несколькими характерными для нее именами и примером ее использования. В этих примерах class_name обозначает имя класса, member - имя члена, object - выражение, задающее объект класса, pointer - выражение, задающее указатель, expr - просто выражение, а lvalue (адрес) - выражение, обозначающее не являющийся константой объект. Обозначение (type) задает имя типа в общем виде (с возможным добавлением *, () и т.д.). Если оно указано без скобок, существуют ограничения.
Порядок применения унарных операций и операций присваивания "справа налево", а всех остальных операций - "слева направо". То есть, a=b=c означает a=(b=c), a+b+c означает (a+b)+c, и *p++ означает *(p++), а не (*p)++.
____________________________________________________________ Операции С++ ============================================================ :: Разрешение области видимости class_name :: member :: Глобальное :: name ____________________________________________________________ .Выбор члена object . member -> Выбор членаpointer -> member [] Индексирование pointer [ expr ] () Вызов функции expr ( expr_list ) () Структурное значениеtype ( expr_list ) sizeof Размер объекта sizeof expr sizeof Размер типа sizeof ( type ) ____________________________________________________________ ++ Постфиксный инкремент lvalue ++ ++ Префиксный инкремент++ lvalue -- Постфиксный декремент lvalue -- -- Префиксный декремент-- lvalue ~Дополнение ~ expr !Логическое НЕ ! expr -Унарный минус - expr +Унарный плюс+ expr &Взятие адреса & lvalue *Косвенность * expr newСоздание (размещение) new type delete Уничтожение (освобождение) delete pointer delete[] Уничтожение массива delete[] pointer () Приведение(преобразование)типа ( type ) expr ____________________________________________________________ . *Выбор члена косвенный object . pointer-to-member ->*Выбор члена косвенный pointer -> pointer-to-member ____________________________________________________________ *Умножениеexpr * expr /Деление expr / expr %Остаток от деления expr % expr ____________________________________________________________ +Сложение (плюс) expr + expr -Вычитание (минус) expr - expr ____________________________________________________________
Все операции таблицы, находящиеся между двумя ближайшими друг к другу горизонтальными чертами, имеют одинаковый приоритет. Приоритет операций уменьшается при движении "сверху вниз". Например, a+b*c означает a+(b*c), так как * имеет приоритет выше, чем +; а выражение a+b-c означает (a+b)-c, поскольку + и - имеют одинаковый приоритет, и операции + и - применяются "слева направо".
____________________________________________________________ Операции С++ (продолжение) ============================================================ << Сдвиг влево expr << expr >> Сдвиг вправо expr >> expr ____________________________________________________________ <Меньше expr < expr <= Меньше или равно expr <= expr >Больше expr > expr >= Больше или равно expr >= expr ____________________________________________________________ == Равно expr == expr != Не равно expr != expr ____________________________________________________________ &Поразрядное Иexpr & expr ____________________________________________________________ ^Поразрядное исключающее ИЛИ expr ^ expr ____________________________________________________________ |Поразрядное включающее ИЛИexpr | expr ____________________________________________________________ && Логическое И expr && expr ____________________________________________________________ || Логическое ИЛИ expr || expr ____________________________________________________________ ? :Операция условия expr? expr : expr ____________________________________________________________ =Простое присваивание lvalue = expr *= Присваивание с умножением lvalue *= expr /= Присваивание с делением lvalue /= expr %= Присваивание с взятием lvalue %= expr остатка от деления += Присваивание со сложением lvalue += expr -= Присваивание с вычитанием lvalue -= expr <<=Присваивание со сдвигом влево lvalue <<= expr >>=Присваивание со сдвигом вправо lvalue >>= expr &= Присваивание с поразрядным И lvalue &= expr |= Присваивание с поразряднымlvalue |= expr включающим ИЛИ ^= Присваивание с поразряднымlvalue ^= expr исключающим ИЛИ ____________________________________________________________ Запятая (последовательность) expr , expr ____________________________________________________________
3.2.1 Скобки
Синтаксис языка С++ перегружен скобками, и разнообразие их применений способно сбить с толку. Они выделяют фактические параметры при вызове функций, имена типов, задающих функции, а также служат для разрешения конфликтов между операциями с одинаковым приоритетом. К счастью, последнее встречается не слишком часто, поскольку приоритеты и порядок применения операций определены так, чтобы выражения вычислялись "естественным образом" (т.е. наиболее распространенным образом). Например, выражение
if (i<=0 || max<i) // ...
означает следующее: "Если i меньше или равно нулю, или если max меньше i". То есть, оно эквивалентно
if ( (i<=0) || (max<i) ) // ...
но не эквивалентно допустимому, хотя и бессмысленному выражению
if (i <= (0||max) < i) // ...
Тем не менее, если программист не уверен в указанных правилах, следует использовать скобки, причем некоторые предпочитают для надежности писать более длинные и менее элегантные выражения, как:
if ( (i<=0) || (max<i) ) // ...
При усложнении подвыражений скобки используются чаще. Не надо, однако, забывать, что сложные выражения являются источником ошибок. Поэтому, если у вас появится ощущение, что в этом выражении нужны скобки, лучше разбейте его на части и введите дополнительную переменную. Бывают случаи, когда приоритеты операций не приводят к "естественному" порядку вычислений. Например, в выражении
if (i&mask == 0) // ловушка! & применяется после ==
не происходит маскирование i (i&mask), а затем проверка результата на 0. Поскольку у == приоритет выше, чем у &, это выражение эквивалентно i&(mask==0). В этом случае скобки играют важную роль:
if ((i&mask) == 0) // ...
Имеет смысл привести еще одно выражение, которое вычисляется совсем не так, как мог бы ожидать неискушенный пользователь:
if (0 <= a <= 99) // ...
Оно допустимо, но интерпретируется как (0<=a)<=99, и результат первого сравнения равен или 0, или 1, но не значению a (если, конечно, a не есть 1). Проверить, попадает ли a в диапазон 0...99, можно так:
if (0<=a && a<=99) // ...
Среди новичков распространена ошибка, когда в условии вместо == (равно) используют = (присвоить):
if (a = 7) // ошибка: присваивание константы в условии // ...
Она вполне объяснима, поскольку в большинстве языков "=" означает "равно". Для транслятора не составит труда сообщать об ошибках подобного рода.