Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
04-09-2015_19-17-13 / Конспект лекций.doc
Скачиваний:
98
Добавлен:
01.03.2016
Размер:
1.31 Mб
Скачать

3.3 Бинарные операции.

Эти операции делятся на следующие группы:

  • аддитивные;

  • мультипликативные;

  • сдвигов;

  • поразрядные;

  • операции отношений;

  • логические;

  • присваивания;

  • выбора компонента структурированного объекта;

  • операции с компонентами классов;

  • операция "запятая";

  • скобки в качестве операций.

Аддитивные операции:

+

бинарный плюс (сложение арифметических операндов к сложение указателя с целочисленным операндом);

-

бинарный минус (вычитание арифметических операнддов или указателей).

Мультипликативные операции:

*

умножение операндов арифметического типа;

/

деление операндов арифметического типа. При целочисленных операндах абсолютное значение результата округляется до целого. Например, 20/3;

равно 6, -20/3 равняется -6

%

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

Операции сдвига (определены только для целочисленных операндов). Формат выражения с операцией сдвига: операнд_левый операция сдвига операнд_правый

<<

сдвиг влево битового представления значения левого цело­численного операнда на количество разрядов, равное зна­чению правого целочисленного операнда;

>>

сдвиг вправо битового представления значения левого це­лочисленного операнда на количество разрядов, равное значению правого целочисленного операнда

Поразрядные операции

&

поразрядная конъюнкция (И) битовых представлений зна­чений целочисленных операндов;

|

поразрядная дизъюнкция (ИЛИ) битовых представлений значений целочисленных операндов;

^

поразрядное исключающее ИЛИ битовых представлений значений целочисленных операндов

Следующая программа иллюстрирует особенности операций сдвига и поразрядных операций.

//Р2.СРР - операции сдвига и поразрядные операции

#include <iostream.h>

void main()

{

cout << "\n 4<<2 равняется " << (4<<2) ;

coot << "\t 5 >>l равняется " << (5>>1) ;

coou << "\n 6&5 равняется " << (6&5);

coat << "\t 6|5 равняется " << (6|5);

coot « "\t 6^5 равняется " << (6^5);

}

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

4<<2 равняется 16 5>>1 равняется 2

6&5 равняется 4 6|5 равняется 7

6^5 равняется 3

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

<

меньше, чем;

>

больше, чем

<=

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

>=

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

==

равно;

!=

не равно;

Операнды в операциях отношения арифметического типа или ука­затели. Результат целочисленный: 0 (ложь) или 1 (истина).

Логические бинарные операции:

&&

конъюнкция (И) арифметических операндов или отношений. Целочисленный результат 0 (ложь) или 1 (истина);

||

дизъюнкция (ИЛИ) арифметических операндов или отношений. Целочисленный результат 0 (ложь) или 1 (истина).

Операции присваивания

В качестве левого операнда в операциях присваивания может ис­пользоваться только модифицируемое l-значение - ссылка на некото­рую именованную область памяти, значение которой доступно изменениям. Термин l-значение (left value), иначе - леводопустимое выражение, происходит от объяснения действия операции присваива­ния, в которой операнд слева от знака операции присваива­ния может быть только модифицируемым l-значением. Примером модифицируемого l-значения служит имя переменной, которой выделена память и соответствует некоторый класс памяти.

=

присвоить значение выражения-операнда из правой части операнду левой части: р = 10.6 - 2*х

*=

присвоить операнду левой части произведение значений обоих операндов:

p *= 2 эквивалентно p = p * 2

/=

присвоить операнду левой части частное от деления значе­ния левого операнда на значение правого:

р /= 2.2 - d эквивалентно р = р / (2.2 - d);

%/

присвоить операнду левой части остаток от деления цело­численного значения левого операнда на. целочисленное значение правого операнда:

n %=3 эквивалентно n = N % 3;

+=

присвоить операнду левой части сумму значений обоих опе­рандов:

A += B эквивалентно а = а + B;

-=

присвоить операнду левой части разность значений левого и правого операндов:

A -= B эквивалентно а = а - B;

<<=

присвоить целочисленному операнду левой части значение, полученное сдвигом влево его битового представления на количество разрядов, равное значению правого целочис­ленного операнда:

а <<= 4 эквивалентно а = a << 4;

>>=

присвоить целочисленному операнду левой части значение, полученное сдвигом вправо его битового представления на количество разрядов, равное значению правого целочис­ленного операнда:

b >>= 4 эквивалентно b = b >> 4;

&=

присвоить целочисленному операнду левой части значение, полученное поразрядной конъюнкцией (И) его битового представления с битовым представлением целочисленного операнда правой части:

c&=7 эквивалентно c = c & 4;

|=

присвоить целочисленному операнду левой части значение полученное поразрядной дизъюнкцией (ИЛИ) его битового представления с битовым представлением целочисленного операнда правой части:

а |=b эквивалентно a = а | b;

^=

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

z ^= х + у эквивалентно z = z ^ (х + у).

Обратите внимание, что для всех операций сокращенная форма присваивания El ор= Е2 эквивалентна E1 = E1 ор (Е2), где ор обозначение операции.

Операции выбора компонентов структурированного объекта

.*

(точка) прямой выбор (выделение) компонента структурированного объекта, например объединения. Формат применения опе­рации:

имя_структурированного_объекта . имя_компонента

->

косвенный выбор (выделение) компонента структурированного объекта, адресуемого указателем. При использовании операции требуется, чтобы с объектом был связан указа­тель. В этом случае формат применения операции имеет вид:

указатель_на_структурированый_объект -> имя_компонента

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

Операции разадресации(*) и адреса(&)

Эти операции используются для работы с переменными типа указатель. Операция разадресации (*) осуществляет косвенный доступ к адресуемой величине через указатель. Операнд должен быть указателем. Результатом операции является величина, на которую указывает операнд. Типом результата является тип величины, адресуемой указателем. Результат не определен, если указатель содержит недопустимый адрес. Рассмотрим типичные ситуации, когда указатель содержит недопустимый адрес:

- указатель является нулевым;

- указатель определяет адрес такого объекта, который не является активным в момент ссылки;

- указатель определяет адрес, который не выровнен до типа объекта, на который он указывает;

- указатель определяет адрес, не используемый выполняющейся программой.

Операция адрес (&) дает адрес своего операнда. Операндом может быть любое именуемое выражение. Имя функции или массива также может быть операндом операции "адрес", хотя в этом случае знак операции является лишним, так как имена массивов и функций являются адресами. Результатом операции адрес является указатель на операнд. Тип, адресуемый указателем, является типом операнда.

Операция адрес не может применятся к элементам структуры, являющимися полями битов, и к объектам с классом памяти register.

Примеры:

int t, f=0, *adress;

adress = &t; /* переменной adress, объявляемой как

указатель, присваивается адрес переменной t */

*adress =f; /* переменной находящейся по адресу, содержащемуся

в переменной adress, присваивается значение

переменной f, т.е. 0 , что эквивалентно

t=f; т.е. t=0; */

Операции с компонентами классов:

*

прямое обращение к компоненту класса по имени объекта и указателю на компонент;

->*

косвенное обращение к компоненту класса через указатель на объект и указатель на компонент.

Комментировать эти операции затруднительно, не введя понятие класса, что будет сделано позже.

Операция указания области видимости

:: операция указания области видимости имеет две формы: бинарную и унарную. Бинарная форма применяется для до­ступа к компоненту класса. Унарная операция '::' позво­ляет получить доступ к внешней для некоторой функции именованной области памяти.

#include <iostream.h>

int k = 15;

void main()

{

int k = 10;

cout << "Внешняя переменная k="<< ::k;

cout << "\nВнутреняя переменная k="<< ++k;

}

Операция последовательного вычисления

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

cout << "Выражение d = 4, d*2 равно "<< (d=4, d*2); // выведет 8

cout << "d равно "<< d; // выведет 4

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

В языке СИ имеется одна тернарная операция - условная операция, которая имеет следующий формат:

операнд-1 ? операнд-2 : операнд-3

Операнд-1 должен быть целого или вещественного типа или быть указателем. Он оценивается с точки зрения его эквивалентности 0. Если операнд-1 не равен 0, то вычисляется операнд-2 и его значение является результатом операции. Если операнд-1 равен 0, то вычисляется операнд-3 и его значение является результатом операции. Следует отметить, что вычисляется либо операнд-2, либо операнд-3, но не оба.

Пример:

max = (d<=b) ? b : d;

Переменной max присваивается максимальное значение переменных d и b.

Круглые '()' u квадратные '[]' скобки играют роль бинарных операций при вызове функций и индексировании элементов массивов.

Круглые скобки обязательны в обращении к функции:

имя_функции (список аргументов)

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

В операции имя_массива[индекс] операндами для операции [] служат имя массива и индекс.

Операция явного преобразования (приведения) типа в языке Си++ имеет две различные формы. Каноническая, унаследованная от языка Си, имеет следующий формат:

(имя_типа) операнд

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

(long) 1 - внутреннее представление имеет длину 4 байта;

(char)1 - внутреннее представление имеет длину 1 байт.

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

имя_типа (операнд)

Она может использоваться только в тех случаях, когда тип имеет простое (несоставное) наименование (обозначение):

long (2) - внутреннее представление имеет длину 4 байта;

double (2) - внутреннее представление имеет длину 8 байтов.

Однако будет недопустимым выражение:

unsigned long(2) // Ошибка!

Операции new, delete для динамического распределения памяти.

Эта еще две особые унарные операции, появившиеся в языке Си++. Он связаны с одной из задач управления памятью, а именно с ее динамическим распределением. Операция

new имя_типа

или

new имя_типа (инициализатор)

Позволяет выделить и сделать доступным свободный участок в основной памяти, размеры которого соответствуют типу данных, определенному именем типа. В выделенный участок заносится значение, вычисляемое инициализатором, который не является обязательным элементом. В случае успешного выполнения операция new возвращает адрес начала выделенного участка памяти. Если участок нужных размеров не может быть выделен (нет памяти), то операция new возвращает нулевое значение адреса (null). Синтаксис применения операции:

указатель = new имя_типа (инициализатор)

Здесь необязательный инициалкзатор - это выражение в круглых скобках, значением которого инициализируется выделяемый участок памяти. Указатель, которому присваивается получаемое значение адреса, должен относиться к тому же типу данных, что и имя_типа операции new.

Пример:

int *t;

double *d;

i = new int(10);

d = new double;

*d=3.14

Для явного освобождения выделенного операцией new участка используется оператор

delete указатель;

где указатель адресует освобождаемый участок памяти, ранее выделенный операцией new. Например, delete d; - освободит участок памяти, связанный с указателем d.

Для освобождения памяти, выделенной для массива, используется следующая модификация того же оператора:

delete [] указатель;

где указатель связан с выделенным для массива участком памяти.

Соседние файлы в папке 04-09-2015_19-17-13