Здесь аргументы специально взяты в скобки — их надо рассматривать как отдельные единичные биты; реальные же примеры не столь очевидны:
(6 and 4) = 4
(6 and 1) = 0
и т.п. Все станет ясно, если 6 и 4 представить как двоичные числа:
0000110 (6) 0000110 (6)
and 0000100 (4) и and 0000001 (1)
______________ ______________
0000100 (4) 0000000 (0)
Впрочем, вовсе не обязательно записывать числа в виде нулей и единиц. Операция and в 99% случаев нужна для двух целей: проверить наличие битов или убрать ( т.е. обнулить) некоторые из них.
Такая проверка нужна, когда число является набором флагов. Например, большое число системных ячеек памяти ПЭВМ содержит сведения о конфигурации машины или ее состоянии. При этом один байт может трактоваться так: бит 6 равен 1 — значит включен режим CapsLock, бит 4 равен 0 — следовательно какой-либо другой режим Lock выключен и т.д. Пусть A содержит этот самый байт с восемью флагами, и надо проверить состояние бита номер 5 (нумерация идет справа налево, от 0 до 7). Единица в бите 5 дает число 25 = 32. Это второй аргумент. Если в A в пятом бите есть единица, то должно выполниться условие
( A and 32 ) = 32
Осталось оформить все это в оператор IF. Можно проверить наличие сразу нескольких «включенных» битов, например, 5-го, 2-го и 0-го. Число с единицами в этих позициях и нулями в остальных равно 2+2 + 1 = 32+4+1 = 37. Если A среди прочих имеет единицы в битах 5, 2 и 0, то в этом случае будет истинным выражение
( A and 37 ) = 37
Исключение или выключение битов достигается следующим образом. Пусть надо исключить бит 3 из переменной A типа Byte (здесь важно знать тип, в который «умещается» текущее значение A). Исключить — значит, задать нулем. Первым делом определяется
- 168 -
число, в котором все биты равны 1, кроме бита номер 3. Для типа Byte оно равно (255 – 23) = 247, где 255 — максимальное значение, вписываемое в байт. Если теперь это число логически умножить на A, то единицы в 247 никак не повлияют на состояние битов в переменной A, а ноль в третьем бите заместит любое значение в A на том же месте. Таким образом, можно записать
A := A and (255 – 8);
чтобы получить значение A с отключенным 3-м битом.
Все это верно и для нескольких битов сразу: если надо исключить биты 3 и 7, то просто запишем
A := A and (255 – 8 – 128);
где 8 = 23 и 128 = 27.
Or — логическое сложение; оно же операция 'ИЛИ', определяется следующими действиями над битами:
[1] or [0] = [0] or [1] = [1]
[0] or [0] = [0]
[1] or [1] = [1]
Квадратные скобки обозначают один бит. Эта операция может с успехом применяться при включении (установки в 1) отдельных битов двоичного представления целых чисел. Так, если надо, чтобы бит 4 значения A стал равным единице, а остальные не изменились, то следует записать
A := A or 16;
где 16 = 24 . При этом не имеет значения, что было в 4-м бите значения A. В любом случае там появится единица.
Аналогичным образом можно включать сразу несколько битов, например, 4-й, 1-й и 0-й:
A := A or (16 + 2 + 1);
Кроме перечисленных, введена еще одна операция xor — исключающее 'ИЛИ' (математическое название — «сложение по модулю 2»). Эта операция возвращает 0, если оба ее аргумента равны, и 1 в противном случае:
[1] xor [1] = [0]
[0] xor [0] = [0]
[1] xor [0] = [0] xor [1] = [1]
Операцию xor можно с успехом применять при смене значения бита (или нескольких битов) на противоположные. Пусть необходимо
- 169 -
переключить состояние бита 5 числа А. Это будет сделано операцией A xor 32 , где 32 = 25.
Исключающее 'ИЛИ' обладает одной особенностью: примененное дважды к одной и той же переменной, оно восстановит ее исходное значение, т.е. всегда выполняется равенство:
A = ( A xor B ) xor B
Следующая группа поразрядных операций — циклические сдвиги (табл. 9.3).
Таблица 9.3
Операция | Название | Форма записи |
shl | Циклический сдвиг влево на N позиций | A shl N |
shr | Циклический сдвиг вправо на N позиций | A shr N |
Приоритет операций shl и shr одинаков и среди всех остальных невысок (см. табл. 9.1). Поэтому, как правило, выражения сдвига должны быть заключены в скобки.
Суть операций shr и shl одинакова: они сдвигают двоичную последовательность значения A на N ячеек (битов) вправо или влево. При этом те биты, которые «уходят» за край разрядности (8, 16 и 32 в зависимости от значения A), теряются, а освободившееся место с другой стороны заполняется нулями (всегда при сдвиге влево и иногда вправо) или единицами (только при сдвиге вправо отрицательных значений типа ShortInt, Integer и LongInt). Например, число с двоичным представлением 11011011 будет трансформироваться при сдвигах влево следующим образом:
( 11011011 shl 0 ) = 11011011
( 11011011 shl 1 ) = 10110110
( 11011011 shl 2 ) = 01101100
( 11011011 shl 3 ) = 11011000
( 11011011 shl 4 ) = 10110000
...
( 11011011 shl 7 ) = 10000000 ( 11011011 shl 8 } = 00000000