2014-07-22 2 views
0

Я работаю над проектом, который содержит переменные разных размеров бит из двоичного файла. Например, одна строка файла (в шестнадцатеричном формате) может выглядеть как «FF C0 AA 00 FE». Из этой строки, например, нужна следующая информация: 4 бита, 7 бит, 11 бит, 8 бит и т. Д. Проблема, с которой я столкнулась, - это некоторые из выделенных чисел будут подписаны, а другие будут беззнаковыми (4 и 7 бит могут быть подписаны, 11 и 8 бит без знака).Как обрабатывать нерегулярные размеры бит

Я изначально извлекал, маскируя и меняя значения Hex, чтобы получить C++ char/short/int из 4, 7, 11, 8 бит. Однако, если я посмотрю на бит в двоичном формате, он будет отображаться как 00001011. Это число должно быть отрицательным, основанным на ведущем 1 (должно быть только 4 бита 1011), но C++ признает его положительным, так как он смотрит на все 8 бит.

Еще один пример для пояснения, я мог бы извлечь 11 бит из файла, который должен быть (11100101101), но в C++ короткий формат, который он отображается как (0000011100101101), должен быть подписан на основе ведущего 1 в 11 бит.

Мне было интересно, каким будет идеальный способ справиться с этим. Я рассматривал возможность создания класса бит/байта, единственная проблема заключается в изменении размеров бит (4,7,11,8).

Спасибо, мы надеемся, что это имеет смысл. Я довольно новичок в двоичном коде на C++, поэтому может быть встроенная функция, которую я не видел.

+0

«FF C0 AA 00 FE» - это последовательность из 4-х, 7-битных, 11-битных, 8-битных, ... данных? – Ben

+1

Как насчет использования структуры [bitfield] (http://en.cppreference.com/w/cpp/language/bit_field)? Или ['std :: bitset'] (http://en.cppreference.com/w/cpp/utility/bitset) также полезен для вашего дела. –

+0

Если FF C0 AA 00 FE из файла, в двоичном формате он отображается как (11111111 1100000 10101010 ...), тогда мне нужно взять первые 4 бита как одно число, поэтому 1111. Затем следующее число равно 7 бит, и это будет 1111110 (4 бита из FF, 4 из C0), 11 бит будут 00000101010 и т. д. – user2840470

ответ

4

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

int make_signed(int value, int bits) 
{ 
    if (value & (1 << (bits - 1))) 
     value |= -1 & ~((1 << bits) - 1); 
    return value; 
} 

Это начинается с проверки того, что будет битом знака в вашем n-битном номере. Если он установлен, верхние биты int также устанавливаются, начиная со значения -1 (все биты, установленные в дополнении 2) и маскируя нижние значащие биты.

+0

+1, но вы можете просто просто сдвинуть дважды, чтобы получить расширение знака (предполагая подписанный тип для 'value'):' value = value << (bits-1) >> (bits-1) '. EDIT: На самом деле, поцарапайте это, это будет работать только в средах, где сдвиг вправо является арифметическим, что специфично для реализации. – Cameron

+0

@Cameron благодарит за то, что я пропустил что-то очень важное. Я придерживаюсь своей оригинальной формулы одним крошечным модом. –

+0

Просто из любопытства: не мог ли он просто сбросить знаковый бит и умножить значение на -1? –

1

Это было сделано для вас - см std::bitset - Просто есть массив из них

+1

std :: bitset не отвечает потребностям пользователей. Он пытается хранить маленькие целые числа, а не коллекции битов. –

1

Вот как вы можете достичь своей цели для двух примеров, приведенных в вашем вопросе:

char src = 0x0B;    // 00001011 
char dst = (char)(src<<4)>>4; // 11111011 

short src = 0x072D;    // 0000011100101101 
short dst = (short)(src<<5)>>5; // 1111111100101101 

В общем, вы можете реализовать функцию для signed значений и функцию для unsigned значений:

#include <limits.h> 

signed int GetSignedVal(signed int val,int numOfBits) 
{ 
    int shift = sizeof(val)*CHAR_BITS-numOfBits; 
    return (val<<shift)>>shift; 
} 

unsigned int GetUnsignedVal(unsigned int val,int numOfBits) 
{ 
    int shift = sizeof(val)*CHAR_BITS-numOfBits; 
    return (val<<shift)>>shift; 
} 
0

В C/C++ редко используется функция, называемая битовым полем, которая устраняет вашу проблему.

struct HodgePodgge { 
      bool oneBooleanBit:1; 
      int fourBitsOfSignedInteger:4; 
      unsigned int sixUnsignedIntegerBits:6; 
    }; 

«SizeOf (мешанина)» должно быть 2 (11 бит всего умещается в двух байтах)

компилятор генерирует код, чтобы сделать перемену, маскирование и знак расширения для вас. Это хорошо, потому что он НЕ гарантирует расположение битов внутри HodgePodge.

This link gives details

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

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