Как найти позицию нескольких бит в байте на python?
Всем привет. Есть число в hex 0x11. Мне необходимо перевести это число в bin и извлечь три флага. flag_1 7й бит, flag_2 4-6 биты, flag_3 0-3 биты. Понимаю как сделать через строки это, но не считаю это верным решением. Нужно применять битовые сдвиги и т.п., но не понимаю как. Прошу помощи. Пример как делаю через строки
num_hex = '11'
str_1 = bin(int(num_hex,16))
while len(str_1) < 8:
str_1 = '0' + str_1
flag_2 = str_1[4:7]
flag_1 = str[7]
flag_2 = int(flag_2)
flag_1 = int(flag_1)
Ответы (2 шт):
Например, так, хотя можно и наоборот сначала делать сдвиг, потом &, но так вроде нагляднее, какие биты берутся:
# flag_1 7й бит, flag_2 4-6 биты, flag_3 0-3 биты
num_hex = '11'
num = int(num_hex,16)
print(bin(num))
flag_1 = ((0b10000000) & num) >> 7
flag_2 = ((0b01110000) & num) >> 4
flag_3 = ((0b00001111) & num)
print(flag_1, flag_2, flag_3)
Вывод:
0b10001
0 1 1
Судя по выводу, вроде правильно.
Ну то есть суть в том, чтобы:
- взять нужные биты по маске используя побитовое "и", т.е.
& - убрать ненужные нули справа с помощью операции "сдвиг вправо", т.е.
>>
import ctypes
c_uint8 = ctypes.c_uint8
class Flags_bits(ctypes.BigEndianStructure):
_fields_ = [
("flag_1", c_uint8, 1),
("flag_2", c_uint8, 3),
("flag_3", c_uint8, 4)
]
class Flags(ctypes.Union):
_anonymous_ = ("b",)
_fields_ = [("b", Flags_bits), ("asbyte", ctypes.c_char)]
def __init__(self, hex=None):
if hex:
self.asbyte = bytes.fromhex(hex)
else:
self.asbyte = b'\x00'
flags = Flags('11')
print(flags.flag_1)
print(flags.flag_2)
print(flags.flag_3)
Если добавить низкоуровневых типов получается красивая высокоуровневая обертка. И сразу работает в обе стороны
flags.flag_3 = 3
print(flags.asbyte)
Flags_bits - структура которая режет байты на биты.
Flags - объединяет один байт со структурой
пс.байт можно заменить на число
Юнион можно не использовать чтоб не захламлять код тем чем не пользуетесь
flags = Flags_bits.from_buffer_copy(bytes.fromhex('11'))
print(flags.flag_1)
print(flags.flag_2)
print(flags.flag_3)