Смекни!
smekni.com

Основы алгоритмизации и программирования 2 (стр. 8 из 32)

Аналогичные действия выполняются и в случае применения оператора |, только результат вычисляется несколько иначе (см. табл. 2.5).

В качестве примера рассмотрим операцию, выполняемую

следующим кодом:

int result, op1, ор2; op1 = 4; ор2 = 5; result = opl & op2;

Здесь необходимо принять во внимание двоичное представление операндов op1 и ор2, соответственно 100 и 101.

Результат этой операции получается путем сравнения двоичных

Бит операнда 1

Бит операнда 2

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

1

1

0

1

0

1

0

1

1

0

0

0

Таблица 2.6-Битовая операция & битов, находящихся в одинаковых позициях в каждом из этих логических представлений:

- первому слева биту результата присваивается значение 1, если оба крайних левых бита op1 и ор2 равны 1, и значение 0 в противном случае;

- следующему биту результата присваивается значение 1, если оба следующих бита op1 и ор2 равны 1, и значение

0 в противном случае;

Таблица 2.7–Логический оператор ~

Бит операнда

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

1

0

0

1

- так продолжается для всех остальных битов.

В данном примере крайние биты слева у обоих операндов op1 и ор2 равны 1, поэтому крайний левый бит результата также будет равен 1. В следующей позиции оба бита равны 0, а в третьей позиции биты равны

Биты

Десятичное представление

Значение

000

0

Черный

100

4

Красный

010

2

Зеленый

001

1

Синий

101

5

Пурпурный

по

6

Желтый

011

3

Голубой

111

7

Белый

Таблица 2.8–Трехбитовое представление цвета соответственно 1 и 0; таким образом, второй и третий биты результата будут равны 0. В качестве окончательного результата в двоичном представлении будет получено число 100, т. е. результат выполнения этой операции будет равен 4.

Аналогичный процесс происходит при использовании оператора |, с тем лишь отличием, что получающийся в результате бит равняется 1 в том случае, если хотя бы один из соответствующих битов операндов равен 1.

Точно таким же способом можно использовать и оператор ^. В этом случае в результате появляется 1, если только у одного из операндов, но не у обоих одновременно,

в соответствующей позиции находится единица.

В языке С# допускается использование унарного оператора работы с битами ~, воздействие которого на операнд состоит в инвертировании (изменении) всех его битов таким образом, что все биты, которые были равны 0, получают значение 1, и наоборот (см. табл. 2.7).

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

Предположим, что мы храним эти значения в переменной типа int. Начиная с черного цвета или, что то же самое, со значения переменной типа int, равного 0, можно выполнить различные операции. Например:

int myColor = 0; bool containsRed; myColor = myColor | 2;

// Добавлен бит зеленого цвета, значение переменной myColor стало 010 myColor = myColor | 4;

// Добавлен бит красного цвета, значение переменной myColor стало 110 containsRed = (myColor & 4) = = 4;

// Выполняется проверка на наличие бита, отвечающего за красный цвет

В результате выполнения последней строки кода значение переменной containsRed будет true, поскольку "красный" бит в переменной myColor равен 1.

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

Помимо описанных выше четырех операторов для работы с битами следует рассмотреть еще два оператора (табл.

2.9).

Таблица 2.9 – Операторы побитового сдвига

Оператор

Тип

Пример выражения

Результат

>>

Бинарный

varl = var2 >> var3;

Переменной varl присваивается значение, которое получается при сдвиге двоичного содержимого переменной var2 вправо на число битов, равное значению переменной var3.

<<

Бинарный

varl = var2 << var3;

Переменной varl присваивается значение, которое получается при сдвиге двоичного содержимого переменной var2 влево на число битов, равное значению переменной var3.

Работу этих операторов, обычно называемых операторами побитового сдвига, лучше всего проиллюстрировать с помощью небольшого примера:

int varl, var2 =10, var3 = 2;
var1 = var2 << var3;

В этом примере переменной varl будет присвоено значение 40. Действительно, двоичное представление числа 10 – "1010"; после сдвига на две позиции влево оно превратится в "101000" – двоичное представление числа 40. То, что мы сделали, можно изобразить как операцию умножения. Каждый бит при сдвиге на одну позицию влево увеличивает свое значение в два раза, соответственно сдвиг на две позиции эквивалентен умножению на 4. И наоборот, при сдвиге всех битов вправо возникает эффект деления операнда на два, при этом любой целый остаток теряется:

int varl, var2 =10; varl = var2 >> 1;

В данном случае varl будет содержать значение 5, а в результате выполнения следующего примера ее значение станет равным 2:

int varl, var2 = 10; varl = var2 >>2;

Маловероятно, что в настоящее время активно пользуются этими операторами, однако знать об их существовании полезно. Их применяют главным образом для получения предельно оптимизированного кода, когда использование других математических операций из-за их большей затратности оказывается неприемлемым. По этой причине рассмотренные здесь операции часто задействуют, например, в драйверах устройств или системных кодах.

2.2.1.Логические операторы присваивания

Последние операторы - это комбинация рассмотренных выше операторов с оператором присваивания. Они во многом сходны с математическими операторами присваивания, рассматривавшимися в предыдущей лекции ( + = , *= и т.д.). Логические операторы приведены в таблице 2.10.

Таблица 2.10 – Логические операторы присваивания

Оператор

Тип

Пример выражения

Результат

&=

Бинарный

varl &= var2;

Переменной varl присваивается значение, являющееся результатом выполнения операции varl & var2.

|=

Бинарный

var1 |= var2;

Переменной varl присваивается значение, являющееся результатом выполнения операции varl I var2.

^=

Бинарный

varl ^= var2;

Переменной varl присваивается значение, являющееся результатом выполнения операции varl * var2.

Эти операторы используются как с логическими, так и с численными значениями, точно так же, как и операторы &, | и ^.

При выполнении операторов &= и |= применяются операторы & и |, а не && и ||, что приводит к издержкам, характерным для этих более простых операторов.

Для операторов побитового сдвига также существуют соответствующие операторы присваивания (табл. 2.11).

Таблица 2.11 – Операторы побитового присваивания

Оператор

Тип

Пример выражения

Результат

>>=

Унарный

varl >> var2;

Переменной varl присваивается значение, которое получается в результате сдвига двоичного содержимого переменной varl вправо на число битов, равное значению переменной var2.

<<=

Унарный

varl << var2;

Переменной varl присваивается значение, которое получается в результате сдвига двоичного содержимого переменной varl влево на число битов, равное значению переменной var2.

2.2.2.Старшинство операторов с дополнениями Старшинство операторов приведено в таблице 2.12.