Побитовые операции и маскировка в C - PullRequest
1 голос
/ 27 мая 2020

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

Первый: скажем, смещение = 4, и у меня есть байт с двоичным кодом 1110 0001. Я хочу замаскировать последние биты размера смещение, так что я могу иметь последний байт 1110 0000 (поэтому замаскируйте последние 4 бита).

Второй: скажем, смещение равно 3, и у меня есть байт с двоичным 1011 0010. Теперь я хочу замаскировать первый несколько битов смещения размера, так что у меня есть последний байт 0001 0010.

Я вставил код, который у меня есть. В настоящее время это не работает для первой маски, которую я хочу создать, поскольку она маскирует первые несколько бит, а не последнюю. Не уверен, правильно ли я создаю маску.

uint8_t mask = (1 << offset) - 1;
byte = (byte & mask);

1 Ответ

1 голос
/ 28 мая 2020

Чтобы замаскировать младшие offset биты, ваши вычисления для mask в порядке, а выражение - нет. Это должно быть:

byte = (byte & ~mask);

или просто:

byte &= ~mask;

Чтобы вычислить маску из смещения с помощью (1 << offset) - 1, вы должны знать, что смещение должно быть меньше количества битов. в виде 1. 1 является int, если означает offset < 32, поэтому вы не можете вычислить маску для 32-битного поля таким образом.

Более того, даже 31 представляет проблему, потому что (1 << 31) превышает ассортимент типа int. Чтобы избежать этого, вы должны написать (1U << offset) - 1 и сначала проверить, offset < 32.

Лучшая альтернатива, которая работает для offset значений от 1 до 32, это:

unsigned mask = ~0U >> (sizeof(unsigned) * CHAR_BIT - offset);
bits &= ~mask;

или проще с противоположной маской:

bits &= ~0U << offset;

Вот макросы для получения, очистки и установки битового поля в unsigned int:

#define GET_MASK(width)               (~0U >> (sizeof(unsigned) * CHAR_BIT - (width)))
#define GET_FIELD(x, pos, width)      (((x) >> (pos)) & GET_MASK(x, width))
#define CLEAR_FIELD(x, pos, width)    (((x) &= ~(GET_MASK(x, width) << (pos)))
#define SET_FIELD(x, pos, width, val) ((x) = ((x) & ~(GET_MASK(x, width) << (pos))) | ((val) << (pos)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...