2014-10-14 5 views
3

Я смотрел на посты о маске, но до сих пор не могу получить мою голову вокруг, как извлечь определенные биты из числа в С.маски и извлекать биты C

Скажем, если у нас есть int number 0001 1010 0100 1011, так это шестнадцатеричное представление x1a4b право? Если я хочу узнать от 5-го по 7-й номер, который в этом случае равен 101, я должен использовать int mask= 0x0000 1110 0000 0000, int extract = mask&number?

Также как я могу проверить, является ли это 101? Думаю, == здесь не сработает ... Большое спасибо!

+0

если вы хотите проверить '5th' и' 7th' число '101 'или нет, тогда сохраните маску как' int mask = 0x0000 1010 0000 0000'. а затем 'ExNOR' это .. если' extract' '5' и' 7th' бит '111', то это' 101' – Haris

+3

Я думаю, что ваш первый номер '0x1a4b' не' 0x1a43'? – ilent2

+0

@ ilent2 извините, мой плохой! исправленный. – stillAFanOfTheSimpsons

ответ

4

Предполагая ССАГПЗ расширение 0b для определения двоичных литералов:

int number = 0b0001101001001011; /* 0x1a4b */ 
int mask = 0b0000111000000000; /* 0x0e00 */ 
/* &'ed:  0b0000101000000000; 0x0a00 */ 
int extract = mask & number;  /* 0x0a00 */ 

if (extract == 0b0000101000000000) 
/* or if 0b is not available: 
if (extract == 0x0a00) */ 
{ 
    /* success */ 
} 
else 
{ 
    /* failure */ 
} 
0

Должен ли я использовать int mask = 0x0000 1110 0000 0000, int extract = mask & number? - Да, вы можете это сделать.

Также, как я могу проверить, если это 101? Уверенный, вы можете это проверить - 0000 1010 0000 0000, который составляет 1280 в инт.

экстракт == 1280

1

Вам нужно маскировать и сдвиг. Либо измените значение, которое вы сравниваете, либо сравниваемое значение. Мне легче думать, переместив значение, которое вы сравниваете. Поэтому, если вы пытаетесь извлечь 5-ю и 7-ю цифры (слева), вы сдвигаете вправо 9 позиций (16-7), так что 7-я цифра теперь самая правая, затем примените 0x7 (111 в двоичном формате) как маска, чтобы получить только крайние правые три двоичных цифр

int i = 0x1A4B; 
if (((i >> 9) & 0x07) == 0x05) { // 0x05 = 101 in binary 
    //do what you need to 
} 
+0

вы переместили соответствующие биты. –

+0

Нет, у меня нет, он отсчет слева, а не справа! – sirlark

+0

@vlad_tepesch: Как это не отвечает на вопрос? – sirlark

2

Маскировка осуществляется путем установки все биты, кроме одного (ов) вы хотите 0. допустим, у вас есть 8 бит переменной а и вы хотите проверить если 5-й бит от 1. Предположим, что ваша переменная равна 00101100. Чтобы скрыть все остальные биты мы установили все биты, кроме 5-ой до 0 с помощью & оператора:

00101100 & 00010000 

Теперь то, что это делает для каждого бита, кроме 5-ой, бит от байта на право будет 0, поэтому результатом операции & будет 0. Для 5-го бита, однако, значение из правого бита равно 1, поэтому результат будет тем, что значение hte 5-го бита из левого байта - в этом случае 0:

Теперь, чтобы проверить это значение, вы должны его сравнить. Чтобы сделать это, просто сравнить результат с байтом справа:

result = (00101100 & 00010000) == 00000000 

Для обобщения этого, вы можете получить любой бит из левостороннего байта просто сдвиг влево 00000001, пока вы не получите немного вы хотите. Следующая функция достигает этого:

int getBit(char byte, int bitNum) 
{ 
    return (byte & (0x1 << (bitNum - 1))) 
} 

Это работает на Варс любого размера, будь то 8, 16, 32 или 64 (или что-нибудь еще в этом отношении).

0

Может быть проще проверять биты один за другим, а не все сразу. Сначала необходимо создать маску для заинтересованного бита:

int fifthBitMask = 1 << 4; 
int fifthBitResult = number & fifthBitMask; 

int seventhBitMask = 1 << 6; 
int seventhBitResult = number & seventhBitMask; 

Теперь вы можете сравнить результаты с нуля или с маской. Сравнивая с нулем можно опустить, так что вы можете просто использовать простой, если:

if (fifthBitResult && seventhBitResult) 
{ 
    //your code here 
} 

Кроме того, вы можете сравнить с масками. После операции & в результате будут установлены только биты, которые были установлены в маске. Таким образом, это может нравится: если (fifthBitResult == fifthBitMask & & seventhBitResult == seventhBitMask) { // здесь ваш код}

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

int mask = 0x5 << 4; // 0x5 is hex representation of 101b 
int result = number & mask; 
if (result == mask) 
{ 
    // your code here 
} 
0

Прежде всего вашего расчета для битов 7-6-5 является incorrct. Вы заявили, что это 101, но это 010 (для x1a43) Во-вторых, чтобы получить эти биты (значение, представленное этими битами), вы должны сделать &0xE0.

int my_bits_from_5to7 = number & 0xE0;

+0

Зависит от того, на каком конце вы начнете рассчитывать. Также зависит, если вы считаете от 0 или 1. – ilent2

+0

@ ilent2 нет, порядок бит на большинстве архитектур всегда один и тот же: справа налево, а первый младший бит всегда равен 0. –

+0

Правда, но если OP незнакомы с поразрядными операциями, вероятно, они также не будут знать о соглашениях: например, подсчет с нуля и справа налево (в то время как английский читается слева направо). – ilent2

1

Во-первых, цифры в бинарном (обычно) отсчитывается от правого (10-й и 12-й цифры), или вы говорите, 5 и 7 значащие цифры.

int mask = 0x0E00; // 0000 1110 0000 0000; 
int extract = mask & number; 

результаты в:

extract = 0000 1010 0000 0000 

Вы можете сделать

if (extract == 0x0A00 /*0000 1010 0000 0000*/){} 

, чтобы проверить, или:

if ((extract >> 9) == 0x05){} 

оба оператора в случае возвращает истину с номер вашего образца.

Обычно с помощью маски вы обнаружите, что испытываете одну цифру. Вы можете использовать функцию, как это проверить:

bool digit_value(unsigned int number, unsigned int digit) 
{ 
    return (1 << digit) & number; 
} 

int main() 
{ 
    unsigned int number = 0x1A4B; 
    int should_be_three = 0; 
    should_be_three += digit_value(number, 10); 
    should_be_three += !digit_value(number, 11); 
    should_be_three += digit_value(number, 12); 
    printf("%s", (should_be_three == 3?"it worked":"it didn't work")); 
    return 0; 
} 
+1

Ваш комсомол неправ; не пытайтесь сравнивать с hex 0x101, но бинарный 101, который равен 0x05 – sirlark

+0

Спасибо! но с 'if ((extract >> 9) == 0x101)', является 'x101' фактически' 0001 0000 0001'? Должно ли это быть 'if ((extract >> 9) == 0b101)'? – stillAFanOfTheSimpsons

+0

Да, я сделал это немного неправильно. Исправлено. (с использованием чистого гекса) – Baldrickk

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