Существует одна BEXTR (извлечение битового поля (с регистром)) x86 для процессоров Intel и AMD и UBFX
для ARM. Существуют встроенные функции, такие как _bextr_u32()
(ссылка требует входа), которые позволяют явно вызывать эту инструкцию.
Они реализуют код (source >> offset) & ((1 << n) - 1)
C: получают n
непрерывные биты от source
, начиная с бита offset
. Вот полное определение функции, которая обрабатывает крайние случаи:
#include <limits.h>
unsigned getbits(unsigned value, unsigned offset, unsigned n)
{
const unsigned max_n = CHAR_BIT * sizeof(unsigned);
if (offset >= max_n)
return 0; /* value is padded with infinite zeros on the left */
value >>= offset; /* drop offset bits */
if (n >= max_n)
return value; /* all bits requested */
const unsigned mask = (1u << n) - 1; /* n '1's */
return value & mask;
}
Например, чтобы получить 3
бит из 2273
(0b100011100001
), начиная с 5
-го бита, вызовите getbits(2273, 5, 3)
- это извлекает 7 (0b111
).
Например, скажем, я хочу первые 17 бит 32-битного значения; что мне делать?
unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff
Предполагается, что CHAR_BIT * sizeof(unsigned)
равно 32 в вашей системе.
Я предполагаю, что должен использовать оператор модуля, и я попробовал его и смог получить последние 8 бит и последние 16 бит
unsigned last8bitsvalue = value & ((1u << 8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff
Если смещение всегда равно нулю, как во всех ваших примерах в вопросе, тогда вам не нужно более общее getbits()
. Существует специальная инструкция процессора BLSMSK, которая помогает вычислить маску ((1 << n) - 1)
.