Как я могу получить доступ к определенной группе битов из переменной? - PullRequest
8 голосов
/ 11 декабря 2010

У меня есть переменная с числом битов "х".Как я могу извлечь определенную группу битов и затем работать с ними в C?

Ответы [ 4 ]

22 голосов
/ 11 декабря 2010

Это можно сделать с помощью последовательности из 2 битовых логических операций.

[[Терминология MSB (msb) является старшим значащим битом;LSB (lsb) - младший бит.Предположим, что биты пронумерованы от lsb == 0 до нескольких msb (например, 31 на 32-битной машине).Значение битовой позиции i представляет коэффициент компонента 2 ^ i целого числа.]]

Например, если у вас есть int x, и вы хотите извлечь некоторый диапазон битов x [мсб..lsb] включительно, например, 4-битное поле x [7..4] из x [31..0] битов, затем:

  1. Смещением x вправо набиты lsb, например, x >> lsb, вы помещаете бит lsb для x в 0-й (наименее значимый) бит выражения, и именно там он должен быть.

  2. Теперь у вас естьмаскировать любые оставшиеся биты выше тех, которые обозначены msb.Количество таких битов равно msb-lsb + 1. Мы можем сформировать строку битовой маски из '1' битов длиной с выражением ~(~0 << (msb-lsb+1)).Например, ~ (~ 0 << (7-4 + 1)) == ~ 0b11111111111111111111111111110000 == 0b1111. </p>

Собрав все это вместе, вы можете извлечь нужный битовый векторв новое целое число с этим выражением:

(x >> lsb) & ~(~0 << (msb-lsb+1))

Например,

int x = 0x89ABCDEF;
int msb = 7;
int lsb = 4;
int result = (x >> lsb) & ~(~0 << (msb-lsb+1));
//      ==   0x89ABCDE  & 0xF
//      ==   0xE (which is x[7..4])

Имеет смысл?

Счастливого взлома!

5 голосов
/ 11 декабря 2010

Если вы имеете дело с примитивом, просто используйте побитовые операции:

int bits = 0x0030;
bool third_bit = bits & 0x0004;  // bits & 00000100
bool fifth_bit = bits & 0x0010;  // bits & 00010000

Если x может быть больше, чем простой примитив, но известен во время компиляции, тогда вы можете использовать std::bitset<> для задачи:

#include<bitset>
#include<string>

// ...
std::bitset<512> b(std::string("001"));
b.set(2, true);
std::cout << b[1] << ' ' << b[2] << '\n';

std::bitset<32>  bul(0x0010ul);

Если x не известен во время компиляции, тогда вы можете использовать std::vector<unsigned char>, а затем использовать битовую манипуляцию во время выполнения. Это больше работы, намерение читается менее очевидно, чем с std::bitset, и медленнее, но это, возможно, ваш лучший вариант для x, изменяющегося во время выполнения.

#include<vector>

// ...
std::vector<unsigned char> v(256);
v[2] = 1;
bool eighteenth_bit = v[2] & 0x02;  // second bit of third byte
2 голосов
/ 11 декабря 2010

работа с битами с &, |.<<, >> операторы.Например, если у вас есть значение 7 (целое число) и вы хотите обнулить 2-й бит:

7 равно 111

(обнуление 2-го бита И это с 101 (5в десятичном виде))

111 & 101 = 101 (5)

вот код:

#include <stdio.h>

main ()
{
    int x=7;

    x= x&5;
    printf("x: %d",x);

}

Вы можете делать с другими операторами, такими как OR, сдвиг влево,сдвиг вправо и т. д.

0 голосов
/ 11 декабря 2010

Вы можете использовать битовые поля в объединении:

typedef union {
unsigned char value;
struct { unsigned b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1; } b;
struct { unsigned b0:2,b1:2,b2:2,b3:2; } b2;
struct { unsigned b0:4,b1:4; } b4;
} CharBits;


CharBits b={0},a={0};
printf("\n%d",b.value);
b.b.b0=1; printf("\n%d",b.value);
b.b.b1=1; printf("\n%d",b.value);
printf("\n%d",a.value);
a.b4.b1=15; printf("\n%d",a.value); /* <- set the highest 4-bit-group with one statement */
...