구조체와 클래스에서는 정수형 또는 논리 변수를 선언할 때 일부 비트만 사용하도록
명시해 줄 수 있습니다.
기술의 발전으로 메모리의 값이 많이 싸졌지만.
빅데이터를 처리할 때나, IoT용 보드 처럼 한정된 메모리 만을 사용해 프로그래밍 해야 하는 경우 등 아직도 메모리를 아껴 쓸 필요가 있는 부분이 존재합니다.
비트 필드는 메모리를 아껴쓰는 방안 중 하나가 될 수 있습니다.
가령 날짜를 예로 들자면 달(Month)을 나타내는 데는
32비트의 정수를 쓸 필요 없이 5비트만 있어도 충분히 값 표현이 가능하지요.
비트 필드의 사용 방법은 다음과 같습니다.
구조체나 클래스 멤버 변수를 선언 할 때
변수명 뒤에 :비트크기 를 붙이는 것입니다.
unsigned short month : 5;
이런식으로요.
다음은 비트 필드의 실제 사용 예를 보여주는 구조체 입니다.
|
weekDay 에 3비트를 할당
monthDay 에 6비트를 할당
month 에 5비트를 할당
year에 8비트를 할당 했습니다.
weekDay 에 값 1
monthDay 에 값 3
month 에 값 7
year 에 값이 15 가 들었을 때 메모리 상에 어떻게 들어가는지 봅시다.
여기서 주의 할 점은
흰색 공간은 사용되지 않는 영역이며, 항상 0값이 들어가 있는것이 아니라
쓰레기 값이 들어가 있을 수 있습니다.
가장 우측 0번 째 비트 부터 시작해서
멤버 변수들이 할당된 비트들을 차지하기 시작하는 데,
중간에 빈 공간이 있습니다.
이유는 바이트 정렬 문제와 관련 있는데, 성능 최적화와 관련이 있습니다.
(CPU 아키텍처에 따라 바이트 정렬이 안된 경우에는 런타임 에러를 일으키기도 하더군요)
바이트 정렬 값의 크기의 중간에 변수가 걸치지 않도록 조정을 해줍니다.
short 타입의 기본 바이트 정렬 크기가 2바이트라
변수를 배치할 때 2의 배수 주소로 변수를 배치하게 됩니다.
0~15번 째 비트를 그룹짓고 (이렇게 특정 크기 단위로 주소에 정렬적으로 잡힌 영역을 pack 이라 부릅니다. 편의상 정렬 공간이라고 부르겠습니다.)
그 안에서 비트필드 변수들의 위치를 잡습니다.
하지만 마지막 year를 넣을 공간이 부족하므로 그 다음 정렬 공간으로. 16~31번 째 비트를 그룹짓고 그 안에서 year 의 위치를 잡은 것입니다.
그렇다면 year를 month 옆에 바짝 붙여서 중간에 빈 공간이 없게 하려면 어떻게 해야 할까요? 바로 weekDay, monthDay, month, year 의 타입을 unsigned int 로 바꾸는 것입니다.
이렇게 하면 int 타입의 바이트 정렬 크기가 4바이트 이므로 0~31 번 째 비트를 그룹짓고 할당하므로 위 네 변수를 충분히 배치할 수 있기 때문에 중간에 빈 공간 없이 배치가 가능합니다.
그리고, 중간에 바이트 정렬을 재설정 하여 변수가 배치될 위치를 다음 정렬 공간으로 바꿀 수 있는 방법이 있습니다.
|
이 때 기준이 되는 정렬 공간의 크기는 0개의 비트를 준 변수의 타입이지요.
unsigned short : 0; 이후의 변수 부터는 16번 째 비트 부터 위치가 잡힘을 알 수 있습니다.
만약
unsigned short : 0; 다음에 month, year의 타입이 unsigned int 였다면 어떻게 될까요?
unsigned short : 0; 로 인해 16번 째 비트 부터 위치를 잡아야 하는데, unsigned int는 4바이트 단위로 정렬하므로 16번 째 비트 부터 할당되지 못하고, 32번 째 비트부터 할당되게 됩니다. 그러면 Date 변수의 크기가 기존보다. 4바이트가 더 늘어나게 되지요.
주의점
CPU는 바이트 단위로 주소를 가져올 수 있습니다.
때문에 비트필드를 사용한 변수는 주소를 가져올 수 없습니다.
&weekDay 와 같은 사용이 불가능합니다.
또한 비트 필드가 메모리를 절약하는데 도움이 되지만 성능은 일반 변수를 사용하는 것보다 좋지 않습니다. 비트필드 변수를 사용할 때 내부적으로 비트 절삭 및 쉬프트를 사용하기 때문 입니다. 메모리를 절실하게 절약할 필요가 있는 상황이 아니라면, 가급적 비트필드를 사용하지 않는것을 추천 드립니다.
댓글 없음:
댓글 쓰기