2009-03-17 3 views
1

그래서 비트 필드 설정 및 조작에 대해 궁금합니다.C++에서 비트 배열의 필드 조작

저는 이미 내 질문과 비슷하지만 C/C++ Code to treat a character array as a bitstream을 찾았습니다.하지만 생각하지 못했던 멋진 stl 접근 방식을 제공하지는 않습니다.

stl의 비트 세트를 생각했지만 데이터 세트는 1,2,3,4,7,8,16 비트 형식의 비트 레이아웃과 매우 복잡합니다.

데이터에서 바이트 경계를 넘는 코드의 8 비트 세그먼트 인 네 번째 필드에 액세스하고 싶다고 쉽게 할 수 있습니까? 나는 4의 데이터에 액세스 또는 4의 데이터를 설정하는 것이 STL 구현을 찾고 있어요

byte 1 byte 2 
11112344 44444455 

, 나는이가 바보 보인다는 단일 바이트로 데이터를 이동해야하고 뭔가가있는 가정 그것을 가면. 그것을 쓰는 것도 어렵고 그러한 일을 성취하기위한 더 쉬운 방법이 있어야하는 것처럼 보입니다.

다른 방법이 있습니까?

편집 - 내 데이터 세트의 길이는 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

브라이언이 말했듯이, 휴대용이 아니며 제 OS와 작동하지 않습니다. –

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>가 열심히하지 않고 다음과 같은 요구 사항이 무엇인지 당신이 생각하는 코드를 마스킹/변속을 최적화 할 수 기본 사용 :

  • 되어이 랜덤 액세스 또는 잇달아 일어나는? (순차적 인 경우 Shift-around 마스크의 재 계산을 피할 수 있습니다.)
  • 모든 요소가 동일한 크기입니까, 임의의 비트 오프셋으로 임의의 크기의 요소를 인덱싱합니까?