Операции

Операции — это действия над данными. Данные, участвующие в операции, часто называют операндами. В качестве операнда может выступать константа, переменная или вызов какой-нибудь функции. Для каждой операции используется соответствующий ей знак операции, состоящий из одного или нескольких символов. В результате выполнения операций всегда получается какое-то значение, представляющее собой результат выполнения операции.

В языке С++ существует большое количество разнообразных операции. Их можно классифицировать по разным признакам, например: по количеству операндов, по назначению, либо как-то ещё.

В зависимости от количества операндов в C++ есть одноместные, двухместные и одна трёхместная операция.

По назначению операции можно сгруппировать таким образом: арифметические, операции сравнения, логические, побитовые, специальные.

Рассмотрим сейчас основные операции, а остальные (специального характера) будем разбирать позже, когда это станет необходимо. В прочем, в таблице ниже приведены все знаки операции, которые имеются в C++, и можно сразу получить о них некоторое представление. Операции в таблице разбиты на группы в соответствии с их рангами.

За исключением операций "[ ]", "( )" и "? :", все знаки операций распознаются компилятором как отдельные лексемы. В зависимости от контекста одна и та же лексема может обозначать разные операции, т.е. один и тот же знак операции может употребляться в различных выражениях и по-разному интерпретироваться в зависимости от контекста. Например, бинарная операция & — это поразрядная конъюнкция, а унарная операция & — это операция получения адреса.

Операции ранга 1 имеют наивысший приоритет. Операции одного ранга имеют одинаковый приоритет, и если их в выражении несколько, то они выполняются в соответствии с правилом ассоциативности либо слева направо (→), либо справа налево (←). Если один и тот же знак операции приведен в таблице дважды (например, знак *), то первое появление (с меньшим по номеру, т.е. старшим по приоритету) соответствует унарной операции, а второе — бинарной.

Приоритеты (ранги) операций

Ранг

Операции

Ассоциативность

1

( )   [ ]   ->   ::   .

2

!   ~   +   -   ++   --   &    *   new   delete   sizeof

3

typeid

4

операторы приведения типа

5

.*   ->*

6

*   /   %   (мультипликативные бинарные)

7

+   -   (аддитивные бинарные)

8

<<   >>   (поразрядного сдвига)

9

<   <=   >=   >   (отношения)

10

==   !=   (отношения)

11

&   (поразрядная конъюнкция "И")

12

^   (поразрядное исключающее "ИЛИ")

13

|   (поразрядная дизъюнкция "ИЛИ")

14

&&   (конъюнкция "И")

15

||   (дизъюнкция "ИЛИ")

16

? :   (условная операция)

17

=   *=   /=   %=   +=    -=   &=   ^=   |=    <<=   >>=

18

,   (операция "запятая")

Арифметические операции

Это наиболее часто используемые операции. Их смысл близок к тому, каким он известен из курса математики. Итак, перечислим их:

Знак операции

Назначение

Пример использования

Результат

+

сложение

2+5

7

-

вычитание

4-1

3

*

умножение

3*5

15

/

деление (обычное)

2.4/2

1.2

/

целочисленное деление

5/2

2

%

вычисление остатка при целочисленном делении

5%2

1

Приоритет операций сложения и вычитания ниже, чем умножения, деления и вычисления остатка. Для изменения порядка вычисления используют круглые скобки, например для умножения на 2 суммы двух чисел A и B можно написать:

2*(A+B)

Далее. Как видно из полученных результатов, в C++ один знак / означает две разные операции. Если один или оба операнда — вещественные, то выполняется обычное деление, если оба операнда — целые, то выполняется деление нацело и результат будет целого типа. Использование этой операции требует повышенной внимательности, например, если запрограммировать вычисление математического выражения

буквально, т.е. так:

1/3*sin(2*X)

то результат вне зависимости от значения X всегда будет равен нулю, так как выражение 1/3 означает деление нацело. Для решения проблемы достаточно один из операндов сделать вещественным

1.0/3*sin(2*X)

Операция вычисления остатка (%) применима только для целочисленных операндов.

Смена знака. Унарная операция «-» означает смену знака. Как видно из общей таблицы всех операций, она имеет очень высокий приоритет — выше, чем, к примеру, у операции умножение. Поэтому в выражении

-A*B

вначале выполняется смена знака для A, а затем умножение -A на B.

Для парности имеется и операция унарный плюс, т.е. можно написать

+A

Для каких целей это использовать? Сложно сказать. Но такая возможность есть.

Более интересны, и главное, очень употребительны операции автоувеличения и автоуменьшения.

Операция автоувеличения (инкремент)

Записывается как два знака плюс (без пробелов между ними!), применяется для увеличения на единицу значения переменной, например:

A++

Исходное значение переменной A увеличивается на 1, и полученный результат сохраняется в переменной A. По полученному результату эта операция соответствует следующему выражению:

A=A+1

хотя на уровне машинных команд — это разные вещи. Операция автоувеличения эквивалентна аналогичной команде INC языка ассемблера. Имеет малый размер кода и выполняется быстрее обычного сложения. На старых процессорах типа Intel 8086 операция инкремента выполнялась в несколько раз быстрее, чем операция сложения.

Важный момент: автоувеличение применимо именно для переменной, но не для константы или выражения.

Для операции инкремент допустимы две формы записи:

При префиксной форме записи делается увеличение переменной на 1 и затем используется новое значение этой переменной.

В постфиксной форме записи также переменная увеличивается на 1, но в текущем выражении используется старое значение переменной.

Рассмотрим это на примерах. Применим постфиксную форму записи. Результат:

Операции

Значение переменной A

Значение переменной B

A=1

1


B=A++

2

1

Префиксная форма записи даёт такой результат:

Операции

Значение переменной A

Значение переменной B

A=1

1


B=++A

2

2

Как видим, переменная A в обоих случаях изменилась на 1 и равна 2, а вот для переменной B результаты получились различными.

Из приведённых примеров следует, что использование операции автоувеличения в выражениях требует от программиста вдумчивого отношения, необходимо чётко представлять, что хотим получить, и что получим в действительности.

Если операция автоувеличения используется как самостоятельный оператор, т.е. как предложение на языке C++, то между обеими формами нет ни какой разницы. Так, операторы

A++; // или

++A;

увеличивают значение переменной A и ничего более, т.е. при таком использовании они, по сути, эквивалентны.

Чаще всего инкремент используют в операторах цикла для увеличения на 1 переменной цикла.

Операция автоуменьшения (декремент)

Записывается как два знака минус (без пробелов между ними!), применяется для уменьшения на единицу значения переменной, например:

A--

Исходное значение переменной A уменьшается на 1, и полученный результат сохраняется в переменной A. По полученному результату эта операция соответствует следующему выражению:

A=A-1

Операция автоуменьшения также имеет две формы записи: постфиксная (A--) и префиксная (--A). В языка ассемблера есть соответствующая ей команда DEC. Это также одна из наиболее быстрых операций. Всё, что было сказано об особенностях работы операции автоувеличения, справедливо и для операции автоуменьшения.

Операции сравнения (операции отношения)

Применяются для сравнения (сопоставления) числовой или символьной информации. Результатом выполнения операций является либо истина (true), либо ложь (false). Перечислим эти операции:

<   меньше;

<=  меньше или равно;

==  проверка на равенство (пишется два знака «равно» без пробелов);

!=  проверка на неравенство;

>   больше;

>=  больше или равно.

Приоритет этих операций ниже, чем у арифметических операций. Пример использования:

A+B>=C

Проверяем: сумма A и B больше С? Если «да», то ответом будет true, если «нет», то false.

В использовании операций сравнения нет ничего сложного. Но следует обратить внимание на одно обстоятельство.

Вещественные числа в памяти хранятся приближенно, при работе с ними в ходе выполнения арифметических операций могут накапливаться погрешности, поэтому не рекомендуется выполнять проверку на равенство или на неравенство для вещественных чисел, т.к. результат может быть непредсказуем. А если очень надо? Что делать?Поступаем просто. Если для вещественных чисел надо выполнить проверку на равенство (типа A==B), то заменяем её на проверку на неравенство вида

|A-B|<=ε,

где ε — некая малая положительная величина эпсилон.

В терминах языка C++ это будет выглядеть так

fabs(A-B)<=eps

Вот и всё решение проблемы. Единственно, не забудьте предварительно задать значение для эпсилон.

Логические операции

Логические операции тесно связаны с операциями сравнения и используются для построения сложных логических выражений. Имеется три логические операции:

Название

Знак операции

Пример записи

Пояснение

Логическое отрицание (НЕ)

!

!X

Если X — истина, то результат — ложь и наоборот

Логическое умножение (И)

&&

X && Y

Результат — истина, если истинны оба операнда

Логическое сложение (ИЛИ)

||

X || Y

Результат — истина, если истинен хотя один операнд

Приоритет операций логического сложения и умножения ниже, чем у арифметических операций и операций сравнения. Зато логическое отрицание имеет очень высокий приоритет.

Пример. Проверить, является ли число A двухзначным. Возможное решение:

A>9 && A<100

Поразрядные (побитовые) операции

Как известно, на компьютере в один приём, т.е. одной операцией, можно обрабатывать только данные размером в 1 байт или более. При этом в ряде случаев необходимо выяснить значения отдельных двоичных разрядов (битов). Для этих целей в языке C++ имеется большой набор операций, позволяющих выполнять различные действия над отдельными битами. Все побитовые операции допустимы только для целых типов. Перечислим эти операции:

Название

Знак операции

Пример записи

Результат выполнения операции

Поразрядное И

&

3&5

1

Поразрядное ИЛИ

|

3|5

7

Поразрядное исключающее ИЛИ

^

3^5

6

Инверсия

~

~3

-4

Поразрядный сдвиг влево

<<

5<<1

10

Поразрядный сдвиг вправо

>>

5>>1

2

При выполнении поразрядной операции И над соответствующими разрядами исходных операндов выполняется операция И. Она напоминает логическую операцию И, но только выполняется с отдельными битами. Если соответствующие биты в обоих операндах равны 1, то и соответствующие бит результата равен 1, иначе он равен 0. Побитовое выполнение этой операции представлено ниже:


Двоичная форма записи чисел


Десятичная форма записи чисел

&

1

0

1


5

0

1

1


3


0

0

1


1

При выполнении поразрядной операции ИЛИ всё происходит аналогично, только над разрядами выполняется операция ИЛИ: результат равен 0, если оба соответствующих разряда равны 0, иначе результат равен 1.

Поразрядное исключающее ИЛИ даёт нам другое правило для вычисления разрядов результата: результат равен 1, если разряды разные, и равен 0, если они одинаковые.

Инверсия — это одноместная операция, заменяющая каждый бит операнда на обратный: 0 на 1, а 1 на 0. Обратите внимание: инверсия — это не смена знака операнда.

Поразрядный сдвиг влево выполняется для разрядов левого операнда на число позиций, равное правому операнду. По результату работы сдвиг влево на k позиций аналогичен умножению исходного числа на .

Поразрядный сдвиг вправо выполняется для разрядов левого операнда на число позиций, равное правому операнду. По результату работы сдвиг право на k позиций аналогичен целочисленному делению исходного числа на .

Операции сдвига работают быстрее, чем операции умножения или деления.

Назад
На верх
Вперёд
Hosted by uCoz