Захват n бит из байта
У меня небольшая проблема с захватом n бит из байта.
У меня есть целое число без знака. Пусть говорят, что наш номер в шестнадцатеричном формате равен 0x2A, что равно 42 в десятичной системе. В двоичном виде это выглядит так: 0010 1010. Как бы я захватил первые 5 бит, которые являются 00101 и следующие 3 бита, которые равны 010, и помещают их в отдельные целые числа?
Если бы кто-нибудь мог мне помочь, это было бы здорово! Я знаю, как извлечь из одного байта, что просто сделать
int x = (number >> (8*n)) & 0xff // n being the # byte
который я видел в другом сообщении при переполнении стека, но я не был уверен, как получить отдельные биты из байта. Если бы кто-нибудь мог мне помочь, это было бы здорово! Спасибо!
Ответы
Ответ 1
Целые числа представляются внутри машины как последовательность бит; к счастью для нас, люди, языки программирования предоставляют механизм, чтобы показать нам эти числа в десятичной (или шестнадцатеричной), но это не изменяет их внутреннего представления.
Вы должны пересмотреть побитовые операторы &
, |
, ^
и ~
, а также операторы сдвига <<
и >>
, которые помогут вам понять, как решить такие проблемы.
Последние 3 бита целого числа:
x & 0x7
Пять бит, начиная с восьми последних бит:
x >> 3 // all but the last three bits
& 0x1F // the last five bits.
Ответ 2
"захват" частей целочисленного типа в C работает следующим образом:
- Вы переносите бит, который вы хотите, в самую низкую позицию.
- Вы используете
&
для маскировки желаемых битов - они означают "копировать этот бит", нули означают "игнорировать"
Итак, в вашем примере. Пусть говорят, что число int x = 42;
первые 5 бит:
(x >> 3) & ((1 << 5)-1);
или
(x >> 3) & 31;
Чтобы получить три нижних бита:
(x >> 0) & ((1 << 3)-1)
или
x & 7;
Ответ 3
Предположим, что вы хотите, чтобы бит hi
был сверху, и lo
бит снизу. (5 и 3 в вашем примере)
top = (n >> lo) & ((1 << hi) - 1)
bottom = n & ((1 << lo) - 1)
Пояснение:
Для вершины сначала избавьтесь от младших бит (сдвиг вправо), затем замаскируйте оставшуюся маску "все" (если у вас есть двоичное число, например 0010000
, вычитая один результат 0001111
- такое же количество 1
, как у вас было 0
-s в исходном номере).
Для дна это то же самое, просто не нужно заботиться о начальном перемещении.
top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b
Ответ 4
Для этого вы можете использовать битовые поля. Бит-биты - это специальные структуры, в которых вы можете указать переменные в битах.
typedef struct {
unsigned char a:5;
unsigned char b:3;
} my_bit_t;
unsigned char c = 0x42;
my_bit_t * n = &c;
int first = n->a;
int sec = n->b;
Бит-поля более подробно описаны на http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION001320000000000000000
Очарование бит-полей - это то, что вам не нужно иметь дело с операторами сдвига и т.д. Обозначение довольно простое. Как всегда при манипулировании битами возникает проблема переносимости.
Ответ 5
просто избавиться от 8 * в вашем коде.
int input = 42;
int high3 = input >> 5;
int low5 = input & (32 - 1); // 32 = 2^5
bool isBit3On = input & 4; // 4 = 2^(3-1)
Ответ 6
int x = (number >> 3) & 0x1f;
даст вам целое число, в котором последние 5 бит представляют собой 8-4 бит number
и нули в других битах.
Аналогично,
int y = number & 0x7;
даст вам целое число с последними 3 битами, установите последние 3 бита number
и нули в остальных.