Native/C
비트 구조체
aucd29
2013. 10. 2. 18:47
비트 구조체는 비트들을 멤버로 가지는 구조체이며 비트 필드(bit field)라고도 부른다. 잘 알다시피 비트는 기억의 최소 단위이며 0 또는 1중 하나를 기억한다. 비트 하나로 2가지 경우, 두 개로 4가지 경우까지 기억할 수 있으며 비트 세 개가 모이면 8가지의 다른 수를 기억시킬 수 있는데 일반적으로 표현하자면 비트 n개가 모이면 2n개의 숫자를 표현할 수 있다.
멤버가 가질 수 있는 값의 범위가 아주 작다면 32비트의 int나 8비트의 char보다 더 작은 단위로 비트를 쪼개 알뜰하게 정보를 기억시킬 수 있는데 이때 사용하는 것이 비트 구조체이다. 비트 구조체를 선언하는 기본 형식은 다음과 같다.
struct 태그명 {
타입 멤버1:비트수;
타입 멤버2:비트수;
타입 멤버3:비트수;
....
};
각 멤버 이름 다음에 이 멤버의 비트 크기를 적어준다. 멤버의 타입은 원칙적으로 정수만 가능하며 부호의 여부에 따라 unsigned int 또는 signed int 둘 중 하나의 타입을 지정한다. 그 작은 공간에도 최상위의 1비트를 부호 비트로 할당할 수 있는데 사실 비트로 표현해야 할 정보는 수치값이라기보다 일종의 기호나 표식인 경우가 많기 때문에 부호를 쓰는 경우는 드물다. 따라서 비트 구조체의 멤버들은 통상 unsigned 타입이다.
원래 C언어 스팩에는 비트 멤버의 타입은 int 또는 unsigned 중 하나만 가능하도록 되어 있으나 마이크로소프트의 비주얼 C++은 short, long, char 등 정수와 호환되는 모든 타입을 허용한다. 그래서 비트 멤버의 타입으로는 모든 정수형을 다 사용할 수 있으며 멤버의 타입에 따라 비트 필드 전체의 크기가 달라진다. double이나 포인터, 배열 따위는 비트 필드가 될 수 없다. 다음 예제는 비트 구조체를 사용하는 가장 간단한 예제이다.
#include <Turboc.h>
struct tag_bit {
unsigned short a:4;
unsigned short b:3;
unsigned short c:1;
unsigned short d:8;
};
void main()
{
tag_bit bit;
bit.a=0xf;
bit.b=0;
bit.c=1;
bit.d=0xff;
printf("크기=%d, 값=%x\n",sizeof(bit),bit);
}
비트 구조체는 메모리를 구성하는 최소 단위인 1비트까지도 알뜰하게 사용할 수 있다는 것이 장점이다. 여러 가지 값들을 꼭 필요한만큼 비트를 잘게 쪼개 값을 기억시킬 수 있으므로 메모리 효율이 아주 좋다. 비트 구조체를 어떤 경우에 사용하는지와 그 장점은 무엇인지 가상적인 게임을 만들면서 자료 구조를 설계해 보도록 하자.
여기서 만들 게임은 일종의 슈팅 게임으로서 화면 위에서 날아오는 적들을 아래쪽의 대포로 쏘아 맞추는 게임이다. 적이 한 종류밖에 없으면 게임의 재미가 없으므로 다양한 종류의 적들을 만들기로 하자. 다음 세 가지 종류를 만든다.
적 유형 0 : 왕파리
적 유형 1 : 똥파리
적 유형 2 : 초파리
각 유형별로 색상도 빨강, 파랑, 노랑, 초록 4가지가 있으며 적이 움직이는 방향도 좌에서 우로, 우에서 좌로 두 가지가 있다고 하자. 또한 총알을 많이 발사하는 못된 놈이 있는가 하면 좀 덜 발사하는 쉬운 놈도 있고 한번 맞아서 죽는 놈도 있고 4번까지 때려야 죽는 끈질긴 놈도 있다. 등장하는 적이 이 정도로 다양해야 게임이 재미있어질 것이다.
그렇다면 이런 적들에 대한 정보를 저장할 수 있는 자료 구조를 만들어 보자. 여러 가지 정보를 하나의 단위로 묶어야 하므로 구조체가 적당하며 최대 100개까지의 적이 한꺼번에 화면에 나타날 수 있도록 하자면 크기 100의 구조체 배열이 필요하다. 다음이 초안이다.
struct tag_enemy {
int type;
int color;
int movetype;
int bullet;
int strike;
} enemy[100];
이렇게 하면 정보를 저장하는데 아무 문제가 없다. 그러나 이 구조체를 다시 살펴 보면 기억 장소를 굉장히 많이 낭비하고 있다는 것을 알 수 있다. 적 유형은 0, 1, 2 셋 중 하나인데 이 정보를 저장할 type 멤버는 -20억~20억까지의 큰 값을 기억할 수 있는 4바이트의 int형으로 되어 있다. short나 char형으로 하면 어느 정도 낭비를 줄일 수 있지만 그래도 낭비는 발생한다. 다른 멤버들도 마찬가지로 int형의 전 범위를 다 사용하지도 않는데 과다하게 기억 장소를 낭비하고 있다. 이럴 때 비트 구조체를 사용한다.
struct tag_enemy {
unsigned char type:2;
unsigned char color:2;
unsigned char movetype:1;
unsigned char bullet:1;
unsigned char strike:2;
} enemy[100];
이렇게 비트 구조체로 바꾸면 적에 대한 정보를 모두 기억시키는 데 단 1바이트밖에 사용하지 않는다. 적 유형은 세 가지가 있으므로 2비트면 충분하고 색상도 네 가지뿐이므로 2비트이면 충분하다. 8비트의 그 좁은 영역에 한 비트, 두 비트씩 잘라서 모든 정보들을 다 기억시킬 수 있다. 더구나 enemy는 크기 100의 배열이기 때문에 절약의 효과가 더욱 두드러진다.
비트 구조체는 메모리를 최대한 절약할 수 있도록 해 주는데 요즘은 비트 구조체를 사용하는 경우가 흔하지 않다. 왜냐하면 과거 메모리가 비쌀 때는 단 1바이트라도 아끼기 위해 이런 복잡한 구조체를 사용했지만 요즘은 메모리가 워낙 풍부해져서 이런 구두쇠짓을 굳이 할 필요가 없어졌다. 더구나 비트 구조체는 크기가 작은만큼 속도에는 불리한 단점이 있으므로 대용량의 정보를 저장할 때 외에는 가급적이면 사용을 자재하는 것이 좋다.
멤버가 가질 수 있는 값의 범위가 아주 작다면 32비트의 int나 8비트의 char보다 더 작은 단위로 비트를 쪼개 알뜰하게 정보를 기억시킬 수 있는데 이때 사용하는 것이 비트 구조체이다. 비트 구조체를 선언하는 기본 형식은 다음과 같다.
struct 태그명 {
타입 멤버1:비트수;
타입 멤버2:비트수;
타입 멤버3:비트수;
....
};
각 멤버 이름 다음에 이 멤버의 비트 크기를 적어준다. 멤버의 타입은 원칙적으로 정수만 가능하며 부호의 여부에 따라 unsigned int 또는 signed int 둘 중 하나의 타입을 지정한다. 그 작은 공간에도 최상위의 1비트를 부호 비트로 할당할 수 있는데 사실 비트로 표현해야 할 정보는 수치값이라기보다 일종의 기호나 표식인 경우가 많기 때문에 부호를 쓰는 경우는 드물다. 따라서 비트 구조체의 멤버들은 통상 unsigned 타입이다.
원래 C언어 스팩에는 비트 멤버의 타입은 int 또는 unsigned 중 하나만 가능하도록 되어 있으나 마이크로소프트의 비주얼 C++은 short, long, char 등 정수와 호환되는 모든 타입을 허용한다. 그래서 비트 멤버의 타입으로는 모든 정수형을 다 사용할 수 있으며 멤버의 타입에 따라 비트 필드 전체의 크기가 달라진다. double이나 포인터, 배열 따위는 비트 필드가 될 수 없다. 다음 예제는 비트 구조체를 사용하는 가장 간단한 예제이다.
#include <Turboc.h>
struct tag_bit {
unsigned short a:4;
unsigned short b:3;
unsigned short c:1;
unsigned short d:8;
};
void main()
{
tag_bit bit;
bit.a=0xf;
bit.b=0;
bit.c=1;
bit.d=0xff;
printf("크기=%d, 값=%x\n",sizeof(bit),bit);
}
비트 구조체는 메모리를 구성하는 최소 단위인 1비트까지도 알뜰하게 사용할 수 있다는 것이 장점이다. 여러 가지 값들을 꼭 필요한만큼 비트를 잘게 쪼개 값을 기억시킬 수 있으므로 메모리 효율이 아주 좋다. 비트 구조체를 어떤 경우에 사용하는지와 그 장점은 무엇인지 가상적인 게임을 만들면서 자료 구조를 설계해 보도록 하자.
여기서 만들 게임은 일종의 슈팅 게임으로서 화면 위에서 날아오는 적들을 아래쪽의 대포로 쏘아 맞추는 게임이다. 적이 한 종류밖에 없으면 게임의 재미가 없으므로 다양한 종류의 적들을 만들기로 하자. 다음 세 가지 종류를 만든다.
적 유형 0 : 왕파리
적 유형 1 : 똥파리
적 유형 2 : 초파리
각 유형별로 색상도 빨강, 파랑, 노랑, 초록 4가지가 있으며 적이 움직이는 방향도 좌에서 우로, 우에서 좌로 두 가지가 있다고 하자. 또한 총알을 많이 발사하는 못된 놈이 있는가 하면 좀 덜 발사하는 쉬운 놈도 있고 한번 맞아서 죽는 놈도 있고 4번까지 때려야 죽는 끈질긴 놈도 있다. 등장하는 적이 이 정도로 다양해야 게임이 재미있어질 것이다.
그렇다면 이런 적들에 대한 정보를 저장할 수 있는 자료 구조를 만들어 보자. 여러 가지 정보를 하나의 단위로 묶어야 하므로 구조체가 적당하며 최대 100개까지의 적이 한꺼번에 화면에 나타날 수 있도록 하자면 크기 100의 구조체 배열이 필요하다. 다음이 초안이다.
struct tag_enemy {
int type;
int color;
int movetype;
int bullet;
int strike;
} enemy[100];
이렇게 하면 정보를 저장하는데 아무 문제가 없다. 그러나 이 구조체를 다시 살펴 보면 기억 장소를 굉장히 많이 낭비하고 있다는 것을 알 수 있다. 적 유형은 0, 1, 2 셋 중 하나인데 이 정보를 저장할 type 멤버는 -20억~20억까지의 큰 값을 기억할 수 있는 4바이트의 int형으로 되어 있다. short나 char형으로 하면 어느 정도 낭비를 줄일 수 있지만 그래도 낭비는 발생한다. 다른 멤버들도 마찬가지로 int형의 전 범위를 다 사용하지도 않는데 과다하게 기억 장소를 낭비하고 있다. 이럴 때 비트 구조체를 사용한다.
struct tag_enemy {
unsigned char type:2;
unsigned char color:2;
unsigned char movetype:1;
unsigned char bullet:1;
unsigned char strike:2;
} enemy[100];
이렇게 비트 구조체로 바꾸면 적에 대한 정보를 모두 기억시키는 데 단 1바이트밖에 사용하지 않는다. 적 유형은 세 가지가 있으므로 2비트면 충분하고 색상도 네 가지뿐이므로 2비트이면 충분하다. 8비트의 그 좁은 영역에 한 비트, 두 비트씩 잘라서 모든 정보들을 다 기억시킬 수 있다. 더구나 enemy는 크기 100의 배열이기 때문에 절약의 효과가 더욱 두드러진다.
비트 구조체는 메모리를 최대한 절약할 수 있도록 해 주는데 요즘은 비트 구조체를 사용하는 경우가 흔하지 않다. 왜냐하면 과거 메모리가 비쌀 때는 단 1바이트라도 아끼기 위해 이런 복잡한 구조체를 사용했지만 요즘은 메모리가 워낙 풍부해져서 이런 구두쇠짓을 굳이 할 필요가 없어졌다. 더구나 비트 구조체는 크기가 작은만큼 속도에는 불리한 단점이 있으므로 대용량의 정보를 저장할 때 외에는 가급적이면 사용을 자재하는 것이 좋다.