2009-03-17 2 views
1

Так что мне интересно, как установить и обработать битовые поля.манипуляция полями в массиве бит в C++

Я уже нашел C/C++ Code to treat a character array as a bitstream, который похож на мой вопрос. Думаю, но это не дает мне приятного подхода stl. Я думаю, должен существовать.

Я думал о битах от stl, но мой набор данных очень сложный с битовыми макетами 1,2,3,4,7,8,16 бит.

Допустим, я хотел получить доступ к элементу в своих данных, 4-е поле, которое представляет собой 8-битный сегмент кода, который пересекает байтовую границу, есть ли простой способ сделать это?

byte 1 byte 2 
11112344 44444455 

Я ищу хороший СТЛ осуществления доступа к данным в 4 или установить данные в 4, я полагаю, что существует нечто, для этого, как это кажется глупым, чтобы перенести данные в один байт и замаскируйте его. написание его также кажется трудным и, как будто должен быть более простой способ выполнить такую ​​задачу.

Есть ли другой способ?

редактировать - мой набор данных составляет около 20 байт в длину и я хочу, чтобы держать все это в разрядном порядке

ответ

1

Можете ли вы объяснить, почему регулярные битовые недостаточно? Другими словами, почему это не так:

struct ComplexBitLayout { 
     unsigned field1 :4; 
     unsigned field2 :1; 
     unsigned field3 :1; 
     unsigned field4 :8; 
     unsigned field5 :2; 
    } __attribute__((__packed__)); // or your compiler's equivalent 

    ComplexBitLayout cbl; 

    cbl.field4 = x; 

делать то, что вы хотите?

Это то, что вы хотите иметь возможность программно строить разные макеты на лету или что-то еще?

+0

Заманчиво использовать бит-поля, но они не переносимы, что часто может быть разбойником. –

+0

Это то, что я ищу, хотя, как сказал Брайан, он не переносится и не работает с моей ОС –

1

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

template<bool> struct CompileTimeAssert; 
template<> struct CompileTimeAssert<true> { }; 

#define ASSERT(check) if (!check) throw exception("Assertion Failure" #check) 

#define ADDBITVALUE(backingField, backingFieldType, fieldName, offset, size) \ 
    public: \ 
    static const unsigned int fieldName##Offset = offset; \ 
    static const backingFieldType fieldName##Mask = CalculateMask<offset, size, backingFieldType>::Value; \ 
    public: \ 
    void Set##fieldName(backingFieldType value) \ 
    {\ 
     ASSERT(("Value too large for field.", (value & (fieldName##Mask >> fieldName##Offset)) == value));\ 
     backingField |= value << fieldName##Offset;\ 
    }\ 
    backingFieldType Get##fieldName() const\ 
    {\ 
     return (backingField & fieldName##Mask) >> fieldName##Offset;\ 
    }\ 
    private: 

#define ADDSPANNEDVALUE(backingField1, backingField1Type, backingField2, backingField2Type, fieldName, offset1, size1, offset2, size2)\ 
    ADDBITVALUE(backingField1, backingField1Type, fieldName##internal1, offset1, size1)\ 
    ADDBITVALUE(backingField2, backingField2Type, fieldName##internal2, offset2, size2)\ 
    public: \ 
    void Set##fieldName(backingField1Type value) \ 
    {\ 
     backingField1Type value1 = value << (sizeof(backingField1Type)*8-size1);\ 
     value1 = value1 >> (sizeof(backingField1Type)*8-size1);\ 
     Set##fieldName##internal1(value1);\ 
     Set##fieldName##internal2(value >> size1);\ 
    }\ 
    backingField1Type Get##fieldName() const\ 
    {\ 
     return Get##fieldName##internal1() | (Get##fieldName##internal2() << size1);\ 
    }\ 
    private: 

template <unsigned int Offset, int Size, typename T> 
struct CalculateMask 
{ 
    CompileTimeAssert<(Size > 0)> Object; 
    static const T Value = (T)((1 << Offset) | CalculateMask<Offset + 1, Size - 1, T>::Value); 
}; 

template <unsigned int Offset, typename T> 
struct CalculateMask<Offset, 0, T> 
{ 
    CompileTimeAssert<(Offset <= sizeof(T) * 8)> Object; 
    static const T Value = 0; 
}; 

Затем определите класс как это:

class BitGroup 
{ 
    unsigned short Values; 
    unsigned short Values2; 
    ADDBITVALUE(Values, unsigned short, Field1, 0, 12); 
    ADDSPANNEDVALUE(Values, unsigned short, Values2, unsigned short, Field2, 12, 4, 0, 2); 
    ADDBITVALUE(Values2, unsigned short, Field3, 2, 14); 
public: 
    BitGroup() : Values(0), Values2(0) {} 
}; 

Использование:

BitGroup bg; 
bg.SetField1(15); 
cout << bg.GetField1(); 
bg.SetField2(63); 
cout << bg.GetField1(); 

Вы получите время компиляции утверждать, если ваши поля выходят за пределы диапазона полей отступающих. Нет проверки того, что поля не перекрываются, поэтому вам нужно будет следить за этим.

+0

, это будет работать для 216 бит? похоже, что это решение для 16 бит –

+0

Вы бы застряли в 64 бит для самого большого поля. – Eclipse

+0

Что, черт возьми, «длинный короткий»? Не определяет постоянные значения, для чего нужны перечисления? –

0

Похоже, что существующие классы, такие как vector<bool> или Boost.DynamicBitset, не будут ничего для вас делать.

Основополагающая реализация должна будет выполнять смену и маскировку, и в этом нет ничего глупого. Дать свой собственный класс или шаблон, используя лежащий в основе vector<bool> или vector<something_else> не так сложно, и тогда вы получите, чтобы оптимизировать переключение передач/маскирование код для того, что вы считаете, что ваши требования, такие как:

  • Является ли это случайный доступ или последовательный? (Если он последователен, вы можете избежать некоторой перераспределения ваших сложенных масок.)
  • Все ли элементы одного размера или вы индексируете элементы произвольного размера при любых смещениях бит?
Смежные вопросы