'비트필드'에 해당되는 글 1건

  1. 2007.10.18 비트필드 사용하기 1

비트필드 사용하기

개발 2007. 10. 18. 09:51

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

제목 : 비트필드 사용하기

저자 : hanburn

날짜 : 2007-10-17

 

 

앞에서 비트벡터에 대해서 알아 보았는데, 이번에는 비트필드에 대해서 알아보도록 하겠습니다. C/C++ 언어에서 비트연산을 제공하고 있지만 바이트의 값에서 원하는 비트의 값을 가지고 오기가 쉽지 않습니다. 예를 들면 윈도우에서 키보드가 눌렸을 때 발생하는 WM_KEYDOWN 메시지에서 LPARAM으로 넘어오는 값은 많은 정보를 가지고 있습니다.

 

0~15 : 키가 반복되는 정보

16~23 : 키 스캔코드(OEM 정보)

24 : 확장정보 오른쪽 ALT/CTRL 키에대한 확장정보

25~28 : 예약필드

29 : context code

30 : 이전 키의 상태 (previous key state)

31 : 변화 상태 (transition state)

 

여기에서 30번째 비트의 정보를 읽어 오려면, shift 연산과 & 연산 등으로 해당 값을 가지고 와야 하는데 너무 번거로운 코드가 들어가야 합니다. 반대로 4바이트의 데이터에 원하는 비트를 설정하려면 비슷한 류의 번거로운 코드가 들어가야 합니다.

 

이러한 번거로운 작업을 편하게 해주는 방법이 비트필드를 이용하는 코딩 방법입니다. 비트필드는 C/C++언어에서 지원을 해주는데 평소에 사용할 일이 없어서 모르는 경우가 많습니다. 비트필드는 바이트단위의 정보를 비트단위로 쪼개어 쉽게 사용할 수 있게 해주는 방법입니다. WM_KYEDOWN에서 사용할 비트필드를 만들어 보면,

 

typedef struct ST_KEYINFO_FIELD

{

        long    repeat:16;

        long    scancode:8;

        long    extendkey:1;

        long    reserved:4;

        long    contextcode:1;

        long    previous_keystate:1;

        long    transition_state:1;

};

 

스트럭처의 변수옆에 : 표현뒤에 오는 숫자는 비트의 크기를 나타냅니다. 숫자를 다 더해보면 16+8+1+4+1+1+1 = 32 가되어 4Byte의 크기로 바로 LPARAM의 크기와 같습니다. Long은 비트필드를 사용할 바이트의 정보로 총 4바이트의 크기의 공간을 예약하고 그 뒤에 오는 숫자로 비트필드의 수를 나타닙니다. 이렇게 구조체를 정의하면  다음과 같이 편하게 값을 읽어오고 쓸수가 있게 됩니다.

 

ST_KEYINFO_FIELD keyInfo;

int a = keyInfo.repeat;       // 반복정보(0~15비트) 읽기

keyInfo.extendkey = 1;        // 확장키정보(24번째비트에) 쓰기

 

 

해당비트의 값을 읽고/쓰기는 편해졌는데, 이렇게 정의된 ST_KEYINFO_FIELD 타입의 변수에 값을 넣기는 그냥 대입을 하면 않됩니다. 아니 그럼 memcpy 등으로 복사를 해야된다는 말인가? 당연히 아니죠~  위의 구조체와 union을 함께 사용하면 됩니다.

 

typedef union ST_KEYINFO

{

        LPARAM lParam;

        ST_KEYINFO_FIELD field;

};

 

공용체를 정의할때는 비트필드와 같은 키기의 변수를 잡는 것이 포인트입니다. 그래야 lparam의 값을 바로 할당 할 수가 있죠. 위에 정의된  ST_KEYINFO 공용체(union)을 사용하여 값을 읽는 코드는 아래와 같습니다.

 

CxxWnd::OnKeyDown(WPARAM wParam, LPARAM lParam)

{

        ST_KEYINFO keyInfo;

        keyInfo.lParam = lParam;

        int a = keyInfo.field.repeat; //

        bool b = keyInfo.field.previous_keystate;   

}

 

공용체(union)와 비트필드를 함께 사용하면 깔끔하게 일정메모리에서 복잡한 비트연산없이 비트단위의 정보를 읽고/쓰기 작업이 편리해 지는 방법입니다.

 

비트벡터보다 훨씬 유용하니까 많이많이 사용하세요



: