Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛР4-С++-13 марта-2012 - копия.doc
Скачиваний:
11
Добавлен:
15.09.2019
Размер:
2.55 Mб
Скачать

1.2. Порядок (старшинство) выполнения операций

Полный список операций (операторов), упорядоченный по приоритетам, приведен в табл. 4.4. Таблица разделена на сегменты двойными линиями. Операторы в каждом сегменте имеют одинаковый приоритет, причем более высокий, чем у операторов в после­дующих сегментах. Например, префиксный оператор инкремента и оператор обра­щения к значению расположены в одном сегменте. Следовательно, они имеют оди­наковый приоритет, превосходящий приоритет арифметических операторов и опе­раторов сравнения. Более подробно некоторые из этих операторов рассматриваются в последующих лабораторных работах.

В языке Си++ определено 19 категорий приоритетов операций. В табл. 4.4 категории приоритетов названы рангами. Операции ранга 1 имеют наивысший приоритет. Операции одного ранга имеют одинаковый приоритет, и если их в выражениях несколько, то они выполняются в соответствии с правилом ассоциативности либо слева направо (Л), либо справа налево (П). Если один и тот же знак операции приведен в таблице дважды, то первое появление (с меньшим но номеру, т.е. старшим по приоритету, рангом) соответствует унарной операции, а второе – бинарной. Отметим, что кроме стандартных режимов использования операций язык С++ допускает расширение их действий на объекты классов, вводимых пользователем или уже определенных в конкретной реализации языка. Примером такого расширения (перегрузки) является операция извлечения данных из потока << и операция передачи данных в выходной поток >>, применяемые к потокам ввода cin и вывода cout.

Таблица 4.4

Приоритеты операций

Ранг

Порядок

Операция

(оператор)

Действие

Применение

1

Л

: :

Глобальная область види­мости

: : имя

1

Л

: :

Область видимости класса

класс::имя

1

Л

: :

Область видимости про­странства имен

пространствоимен::имя

2

Л

.

Обращение к члену класса

объект.член

2

Л

- >

Обращение к члену класса

указатель->член

2

Л

[]

Индексирование

переменная [выражение]

2

Л

()

Вызов функции

имя(список_выражений)

2

Л

()

Создание типа

тип(список_выражений)

3

П

++

Постфиксный инкремент

1 -значение++

3

П

--

Постфиксный декремент

1-значение--

3

П

typeid

Идентификатор типа

typeid(тип)

3

П

typeid

Идентификатор типа вре­мени выполнения

typeid(выражение)

3

П

Явное

приведение

Преобразование типов

имя_приведения<тип>(выражение)

4

П

sizeof

Размер объекта

sizeof выражение

4

П

sizeof

Размер типа

sizeof(тип)

4

П

++

Префиксный инкремент

++1 -значение

4

П

--

Префиксный декремент

- -1 -значение

4

П

~

Побитовый NOT

~выражение

4

П

!

Логический NOT

!выражение

4

П

-

Унарный минус

-выражение

4

П

+

Унарный плюс

+выражение

4

П

*

Обращение к значению

*выражение

4

П

&

Обращение к адресу

&выражение

4

П

()

Преобразование типов

(тип) выражение

4

П

new

Создание объекта

new тип

4

П

delete

Освобождение объекта

delete выражение

4

П

delete []

Освобождение массива

delete [] выражение

5

Л

->*

Указатель на член класса

указатель ->* указатель_на_ член

5

Л

. *

Указатель на член класса

объект .* указатель_на_ член

6

Л

*

Умножение

выражение * выражение

6

Л

/

Деление

выражение / выражение

6

Л

%

Деление по модулю (остаток)

выражение % выражение

7

Л

+

Сумма

выражение + выражение

7

Л

-

Разница

выражение - выражение

8

Л

<<

Побитовый сдвиг влево

выражение << выражение

8

Л

>>

Побитовый сдвиг вправо

выражение >> выражение

9

Л

<

Меньше

выражение < выражение

9

Л

< =

Меньше или равно

выражение <= выражение

9

Л

>

Больше

выражение > выражение

9

Л

> =

Больше или равно

выражение >= выражение

10

Л

==

Равенство

выражение == выражение

10

Л

!=

Неравенство

выражение != выражение

11

Л

&

Побитовый AND

выражение & выражение

12

Л

^

Побитовый XOR

выражение ^ выражение

13

Л

|

Побитовый OR

выражение | выражение

14

Л

&&

Логический AND

(конъюнкция «И»)

выражение && выражение

15

Л

||

Логический OR

(дизъюнкция «ИЛИ»)

выражение || выражение

16

П

?:

Условная операция

выражение ? выражение : выражение

17

П

=

Присвоение

1-значение = выражение

17

П

*=, /=, %=,

Составные

операторы

присвоения

1-значение += выражение

и т.д.

17

П

+=, -=

17

П

<<=, >>=

17

П

&=, |=, ^=

18

П

throw

Передача исключения

throw выражение

19

Л

,

Запятая

выражение , выражение

Порядок определяет последовательность группировки операций (операторов) при одинако­вом уровне приоритета. Вопросы порядка весьма существенны и в некоторых других случаях. Например, правосторонний порядок (П) оператора присвоения позволяет соз­давать составные операторы присвоения.

ival - jval = kval = lval // правосторонний порядок

(ival = (jval = (kval = lval))) // эквивалентная версия со скобками

Это выражение сначала присваивает значение переменной lval переменной kval, полученный результат присваивается переменной jval и, наконец, перемен­ной ival.

Арифметические операторы, напротив, имеют левосторонний порядок (Л).

ival * jval / kval * lval // левосторонний порядок

(((ival * jval) / kval) * lval) // эквивалентная версия со скобками

В этом выражении, например, происходит умножение значений переменных ival и jval, затем деление результата на значение переменной kval и, наконец, умножение результата деления на lval.

Замечание: поскольку в лабораторных работах с 1-й по 5-ю используются исключительно арифметические операции, то при написании программ на С++ удобнее пользоваться на первых порах более простой и компактной табл. 3.4 (лабораторная работа № 3), в которой приведен приоритет (ранг) только арифметических операций. Начиная с лабораторной работы 6 при написании программ на языке С++ будут использоваться по мимо арифметических операций и другие операции языка С++, в этом случае необходимо обращаться к табл. 4.4.

В заключение рассмотрения работы с арифметическими операциями отметим, что приоритет операций умножения и деления выше приоритета операций сложения и вычитания. Это означает, что сначала выполняются операции умножения и деления и только затем операции сложения и вычитания. Пример 4.1 демонстрирует приоритет арифметических операций:

Пример 4.1.

double n=2, SCALE = 1.2;

double arg = 25.0 + 60.0*n/SCALE;

В приведенном примере сначала будет выполнена операция умножения, затем деления и, наконец, сложения. То есть порядок вычисления соответствует математическим правилам. Для того чтобы изменить порядок вычисления (поменять приоритеты) используются круглые скобки как показано ниже

Результат выражения зависит от группировки составляющих его операторов. Например, при вычислении выражения в примере 4.2 слева направо получится 20.

Пример 4.2.

6+3*4/2+2;

Для выражения примера 4.2 вполне возможны и другие результаты: 9, 14 и 36. Напомним, что в языке С++ результат вычисления выражения со­ставит 14.

Умножение и деление имеют более высокий приоритет, чем сложение. Их опе­ранды связаны с операторами жестче, чем операнды операторов сложения. Умноже­ние и деление имеют одинаковый приоритет. Операторы имеют также порядок выполнения, который определяет последовательность группировки операндов у операторов с одинаковым уровнем приоритета. Арифметические операторы имеют левосторонний порядок, т.е. они группируются слева направо. Теперь вполне оче­видно, что приведенное выше выражение можно переписать следующим образом.

int temp = 3*4 //12

int temp2 = temp /2 //6

int temp3 = temp2 + 6 //12

int result = temp3 + 2 // 14

1.3. Управление порядком, в котором C++ выполняет операции

Круглые скобки позволяют переопределить приоритет операций!

Как вы уже знаете, C++ назначает операциям различный приоритет, который и управляет порядком выполнения операций. К сожалению, иногда порядок, в котором C++ выполняет арифметические операции, не соответствует порядку, в котором вам необходимо их выполнить. Например, предположим, что вашей программе необходимо сложить две стоимости и затем умножить результат на налоговую ставку:

Пример 4.3.

cost = price_a + price_b * 1.06;

К сожалению, в этом случае C++ сначала выполнит умножение (price_b * 1.06), а затем прибавит значение price_a.

Для переопределения приоритета можно использовать круглые скобки. Выраже­ния в круглых скобках обрабатываются как отдельные модули. Когда C++ оценивает выражение, он сначала всегда выполняет операции, сгруппированные в круглых скобках, а во всех остальных случаях применяется обычные правила приоритета.

Пример 4.4.

Рассмотрим следующее выражение:

result =(2+3)* (3+4);

C++ вычисляет данное выражение в следующем порядке:

result = (2 + 3) * (3 + 4);

= (5) * (3 + 4);

= 5 * (7);

=5*7;

= 35;

Пример 4.5.

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

// круглые скобки позволяют изменить стандартный приоритет

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

cout << ((6 + ((3 * 4) / 2)) + 2) << endl; //результат 14

// круглые скобки позволяют создать альтернативные группировки

cout << (6+3) * (4/2+2) << endl; //результат 36

cout << ((6+3) * 4) /2+2 << endl; //результат 20

cout << 6+3*4/ (2+2) << endl; // результат 9

В качестве примера рассмотрим следующее вы­ражение:

*iter++;

Приоритет оператора ++ выше приоритета оператора *. Это значит, что сначала выполняется часть iter++,a ee результат становится операндом оператора *. Таким образом, обращение к значению итератора iter происходит после его инкремента. Но если бы необходимо было увеличить значение, на которое указывает итератор iter, пришлось бы применить круглые скобки, чтобы явно указать свои намерения.

(*iter)++; // увеличить значение, на которое указывает

// итератор iter

Круглые скобки указывают, что операнд * применяется к итератору iter. Те­перь как операнд оператора ++ в выражении используется часть *iter.

Группируя выражения внутри круглых скобок, вы можете управлять порядком, в котором C++ выполняет арифметические операции.

Пример 4.6.

Для задания правильного алгоритма вычислений в примере 4.6, необходимо сложить две стоимости внутри круглых скобок, как показано ниже:

cost = (price_a + price_b) * 1.06;

Рекомендация: в сомнительных случаях сами доопределяйте приоритет операций с помощью круглых скобок.

Пример 4.7:

2 + 2 * 2 = 6; (2 + 2) * 2 = 8.