Битовое поле
Битовое поле — в программировании число, занимающее некоторый набор битов, напрямую не адресуемый процессором. Например: при 8-битном байте первые два поля протокола IP — версия и IHL — будут битовыми полями. На машинах с 32-битным байтом все поля IP-пакета (кроме IP-адресов отправителя и получателя) будут битовыми.
Обращение к битовым полям требует дополнительных команд процессора для маскирования и сдвига, и потому медленнее обращений к словам/байтам. Поэтому битовые поля применяются для максимально полной упаковки информации в местах, где неважна скорость доступа к информации.
Компиляторы, как правило, ограничивают работу с битовыми полями только извлечением значения битового поля и записью значения в битовое поле, а само битовое поле воспринимается как беззнаковое число. Реальный порядок следования битовых полей в структуре является системно-зависимым: в одних компиляторах битовые поля могут быть расположены начиная с младших битов, а в других — со старших.
Операции над многобитовыми полями
Пусть в одном байте находятся три битовых поля: 1-битовые a и b, 2-битовое c и 4-битовое d, то есть <math>x = a + b \cdot 2^1 + c \cdot 2^2 + d \cdot 2^4</math>.
[старший бит] d d d d c c b a [младший бит]
Например: при a=1, b=0, c=2=102, d=5=01012 получаем x=010110012=89.
Сборка одного числа из битовых полей
Двоичные компьютеры обычно имеют команды побитового сдвига, которые позволяют быстро умножать на степени двойки — 2, 4, 8 и т. д. Вместо сложения можно применить команду логического «ИЛИ». Таким образом, число x можно собрать и по-другому:
x = (d << 4) | (c << 2) | (b << 1) | a
Извлечение битового поля
Для извлечения битового поля нужно провести две операции:
- Умножить операцией логического «И» число на битовую маску — число, у которого в соответствующих разрядах единицы, а в остальных нули.
- Провести побитовый сдвиг вправо.
То есть:
c = (x & 00001100b) >> 2
Либо:
- Провести побитовый сдвиг вправо.
- Умножить операцией логического «И» число на битовую маску соответствующей длины.
c = (x >> 2) & 00000011b
Для младшего поля побитовый сдвиг не нужен, то есть:
a = x & 00000001b
Для старшего поля побитовый сдвиг сам по себе, без умножения на маску, очистит x от ненужных битов — то есть,
d = x >> 4
Замена битового поля
- Очистить x от предыдущего значения побитовым умножением на маску с нулями в соответствующих битах.
- Побитово сложить x с новым значением (сдвинутым на нужное количество битов)
Например, если нам нужно заменить d, то
xnew = (x & 00001111b) | (d << 4)
Операции над однобитовыми полями
Поля a и b имеют длину 1 бит — это позволяет работать с ними несколько другими средствами.
Проверка отдельного бита
Для проверки надо побитово умножить x операцией «И» на маску, у которой одна единица — в соответствующей позиции. Если получился 0, бит равен 0.
b = ((x & 00000010b) != 0)
Проверка, равен ли единице хотя бы один бит из нескольких:
a_or_b = ((x & 00000011b) != 0)
Проверка, равны ли единице все биты из нескольких:
a_and_b = ((x & 00000011b) == 00000011b)
Установка битов
Для этого надо сложить операцией «ИЛИ» x с маской, у которой единицы в соответствующих позициях. Например, чтобы включить бит a:
x1 = x | 00000001b
Чтобы включить и a, и b:
x2 = x | 00000011b
Снятие битов
Чтобы снять один или несколько битов, надо сложить x операцией «И» с маской, у которой в соответствующих позициях нули. В частности, чтобы выключить бит b, нужно дать команду:
x3 = x & 11111101b
Переключение битов
Для переключения битов (с 0 на 1, с 1 на 0) надо сложить x командой «Исключающее ИЛИ» с маской, у которой в соответствующих позициях единицы. Например, бит b переключается так:
x4 = x ^ 00000010b
Операции над знаковыми полями в дополнительном коде
Существуют два способа хранения отрицательных целых чисел — знаковый бит и дополнительный код. В подавляющем большинстве современных машин применяется второй. При записи отрицательных чисел дополнительным кодом имеем:
-1 = 11111111b -2 = 11111110b -3 = 11111101b -4 = 11111100b и т. д.
Считаем, что поля c и d имеют именно такой формат. Тогда поле c может хранить числа от −2=102 до 1=012, а поле d — от −8=10002 до 7=01112.
Сборка и замена чисел
Каждое из слагаемых (кроме старшего), чтобы оно не испортило более старшие разряды, требуется умножать на битовую маску соответствующей длины. В частности:
x = (d << 4) + ((c & 00000011b) << 2) + (b << 1) + a
Извлечение чисел
Для извлечения чисел требуется сдвинуть поле на нужное количество битов вправо, заодно размножив знаковый бит. Например, для этого можно воспользоваться арифметическим сдвигом. Если x имеет длину 8 битов, то
c = (x << 4 ) >>a 6 d = x >>a 4
Внимание! В языке программирования Java всё наоборот: знаком >>
обозначается арифметический сдвиг, знаком >>>
— простой.
Если арифметического сдвига нет, то…
c1 = x >> 2 если (c1 & 00000010b ≠ 0) то c = c1 | 0x11111100b иначе c = c1 & 0x00000011b
Ошибка: неверное или отсутствующее изображение |
Для улучшения этой статьи желательно?:
|
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....