BIT_SET 매크로를 이용한 bitmap 자료구조 구현
에서는 bitmap 자료구조를 사용해야 하는 경우가 있는데, 리눅스 커널에는 bitmap을 사용하기 위한
자료구조와 매크로가 이미 정의되어 있다.
먼저 간단히 개요부터 살펴보기로 하자.
1. bit_set 구조체 : int[32]형 배열을 사용한 32*4*8=1024개의 bit field를 가진 bitmap이다.
2. BIT_ZERO(x) 매크로 : bit_set 내의 모든 bit field를 0으로 초기화하는 매크로이다.
3. BIT_SET(x, index) 매크로 : bit_set 내의 index를 1로 setting하는 매크로이다.
4. BIT_CLR(x, index) 매크로 : bit_set 내의 index를 0으로 setting하는 매크로이다.
5. BIT_ISSET(x, index) 매크로 : bit_set 내의 index가 1로 되어있는지를 확인하는 매크로이다.
먼저 bitmap 자료구조인 bit_set 구조체부터 살펴보자.
typedef struct {
int data[32];
} bit_set;
앞의 설명대로, 크기가 32인 int형 배열을 구조체로 wrapping한 형태이다.
int는 32bit이므로, 32*32=1024개의 bit수를 가진 자료구조이다.
다음은 BIT_매크로 시리즈 코드를 살펴보도록 하자.
#define BIT_SET(x, index ) ((x)->data[index>>5] |= 1<<(index&31))
#define BIT_ISSET(x, index ) ( (x)->data[index>>5] & ( 1<<(index&31)) )
#define BIT_CLR(x, index ) ((x)->data[index>>5] &= ~(1<<(index&31)))
#define BIT_ZERO(x) do {int i; \
for(i=0; i<32; i++ ) \
(x)->data[i] = 0; \
} while(0)
매크로가 조금 복잡해 보이지만, 차근차근 보면 알 수 있다.
x에는 bit_set 구조체 변수 이름이 들어가며, index에는 bitmap 인덱스를 넣어주면 된다.
index의 범위는 0~1023이지만 bit_set의 내부 구조는 크기 32인 배열이기 때문에 index를 통해 배열을 선택하기 위해 index>>5를 해준다.(32=2^5 이므로)
그리고 배열 내에서의 index는 하위 5bit가 되므로 (index&31) 연산으로 구할 수 있다.
위의 연산들을 통해 bit_set 내에 각 bit를 설정하거나 확인할 수 있는 것이다.
아래의 예시 코드를 통해 사용 방법을 좀 더 알아보도록 한다.
#define BIT_SET(x, index ) ((x)->data[index>>5] |= 1<<(index&31))
#define BIT_ISSET(x, index ) ( (x)->data[index>>5] & ( 1<<(index&31)) )
#define BIT_CLR(x, index ) ((x)->data[index>>5] &= ~(1<<(index&31)))
#define BIT_ZERO(x) do {int i; \
for(i=0; i<32; i++ ) \
(x)->data[i] = 0; \
} while(0)
typedef struct {
int data[32];
} bit_set;
int main() {
int i;
bit_set item;
BIT_ZERO(&item);
BIT_SET(&item, 700);
BIT_SET(&item, 800);
for(i=0; i<1024; i++) {
if( BIT_ISSET( &item, i))
printf("%d\n", i);
}
printf("-----------------------\n");
BIT_CLR( &item, 800);
for(i=0; i<1024; i++) {
if( BIT_ISSET( &item, i)) {
printf("%d\n", i);
}
}
return 0;
}