2013-03-06 5 views
10

У меня есть небольшая проблема с захватом n бит из байта.Захват n бит из байта

У меня есть целое число без знака. Скажем, наш номер в шестнадцатеричном формате равен 0x2A, что равно 42 в десятичной системе. В двоичном виде это выглядит так: 0010 1010. Как бы я захватил первые 5 бит, которые являются 00101 и следующие 3 бита, которые равны 010, и помещают их в отдельные целые числа?

Если бы кто-нибудь мог мне помочь, это было бы здорово! Я знаю, как извлечь из одного байта, который должен просто сделать

int x = (number >> (8*n)) & 0xff // n being the # byte 

, который я видел на другой пост на переполнение стека, но я не был уверен в том, как получить отдельные биты из байта. Если бы кто-нибудь мог мне помочь, это было бы здорово! Благодаря!

+0

Первые 5 (MSB) битов 42 равны 00000, потому что int всегда больше 1 байта. Кроме того, нет такого понятия, как целое число без знака, которое имеет десятичную форму шестнадцатеричного кода. 'int a = 0x2A;' то же самое, что и запись 'int a = 42;' – user93353

ответ

14

Целые числа представлены внутри машины как последовательность бит; к счастью для нас, люди, языки программирования предоставляют механизм, чтобы показать нам эти числа в десятичной (или шестнадцатеричной), но это не меняет их внутреннего представления.

Вы должны пересмотреть битовые операторы &, |, ^ и ~, а также операторы сдвига << и >>, которые помогут вам понять, как решать подобные проблемы.

Последние 3 бита целого числа являются:

x & 0x7 

Эти пять битов, начиная с восьми последнего бита являются:

x >> 3 // all but the last three bits 
    & 0x1F // the last five bits. 
+0

. Как это сравнивается по производительности с сохранением двух подтемов в виде двух 32-битных целых чисел? Добыча займет некоторое время, но это 32 операции медленнее? – Kammeot

+0

@InspiredOne: таких вопросов невозможно точно ответить абстрактно, но очевидно, что это улучшает использование памяти (в восемь раз по сравнению с двумя 32-битными целыми числами или в два раза по сравнению с двумя байтами), что улучшает производительность кеша, пропускную способность памяти и пропускную способность, если это необходимо (время передачи или вторичное хранилище). Поскольку стоимость процессора тривиальна по сравнению с любым из этих факторов, сжатые данные обычно будут быстрее, если вам нужно много экземпляров; это не стоит делать для одной пары переменных (но это тоже не сильно больно). – rici

1

просто избавиться от 8 * в вашем коде.

int input = 42; 
int high3 = input >> 5; 
int low5 = input & (32 - 1); // 32 = 2^5 
bool isBit3On = input & 4; // 4 = 2^(3-1) 
1

int x = (number >> 3) & 0x1f;

даст вам целое число где последние 5 бит - это 8-4 бит number и нули в других битах.

Аналогично,

int y = number & 0x7;

даст вам целое с 3 последних битов устанавливают последние 3 бита number и нули в остальных.

7

Скажите, что вы хотите 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 
12

«хватают» части целочисленного типа в C работает следующим образом:

  1. Вы сдвигают биты, которые вы хотите в самое нижнее положение.
  2. используется & маскировать биты вы хотите - те, значит, «копию этого бита», нули означают «игнорировать»

Итак, в вас пример. Скажем, у нас есть ряд int x = 42;

первые 5 бит:

(x >> 3) & ((1 << 5)-1); 

или

(x >> 3) & 31; 

принести нижние три бита:

(x >> 0) & ((1 << 3)-1) 

или:

x & 7; 
2

Вы можете использовать битподы для этого. Битовые поля - это специальные структуры, в которых вы можете указать переменные в битах.

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

Обаяние битовых полей, что вам не придется иметь дело с операторами сдвига и т.д. нотация довольно легко. Как всегда при манипулировании битами возникает проблема переносимости.

Смежные вопросы