Programming/C C++

0과 1이나 true/false같은 switch개념의 변수를 사용하려면 C언어에서 최소사양에 해당하는 char형을 생각해 볼 수 있습니다. 물론 int형이나 그 밖에 다른 형을 써도 상관은 없지만 1Bit만 있으면 되므로 굳이 많은 Data형을 할당하여 Memory를 낭비할 필요는 없습니다.

그런데 char형도 그리 효츌적이지는 않습니다. 왜냐하면 char는 1Byte단위(8bit)이므로 0과 1을 표시하는데 1Bit를 할당하고 나면 나머지 7Bit는 결국 낭비되기 때문입니다.

따라서 C에서는 Bit단위의 Data를 다룰때 해당 Bit영역을 최대한 활용하기 위해 Bit Field라는 것을 사용합니다.

Bit Field는 선언하고자 하는 Data형의 크기 만큼 Bit Field를 구조체 형식으로 선언하면 됩니다.

struct bitfield{
    unsigned char a : 1;
    unsigned char b : 1;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
    unsigned char f : 1;
    unsigned char g : 1;
    unsigned char h : 1;
};

bitfield라는 이름으로 unsigned char형(8bit)의 a부터 h까지 Bit Field를 선언하였습니다.

unsigned char라고 한 이유는 char형의 전체 8Bit중 최상위 Bit(부호를 정하는 bit)까지 모두 사용하기 위해서 입니다.(만약 unsigned int라고 한다면 16Bit만큼을 의미하게 됩니다.)

unsigned char는 전체 8bit이므로 a부터 h까지 1비트씩 차지하여 결국 합이 1Byte의 Memory를 할당하게 됩니다. 이때 a부터 h까지 1Bit씩 차지한다는 것은 a : 1 등에 의해 정해지게 됩니다.

따라서 1Bit가 아닌 그 이상의 Bit를 할당하고자 할 경우에는 오른쪽의 숫자만 바꾸어 주면 될것입니다.

struct bitfield{
    unsigned char a : 2;
    unsigned char b : 3;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
};

a는 2Bit, b는 3Bit.. 나머지는 모두 1Bit를 할당하였습니다. 따라서 a는 2Bit이므로 0~3까지 그리고 b는 3Bit이므로 최소 0~7까지의 Data를 담을 수 있습니다.

이때 만약 Data형의 범위를 벗어나도록 bit field를 지정하면 어떻게 될까요?

struct bitfield{
    unsigned char a : 2;
    unsigned char b : 3;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
    unsigned char f : 1;
};

f 1Bit까지 전체 9Bit를 할당하였습니다.

unsigned char는 8bit이므로 f를 수용할 수 없습니다. 하지만 Compiler는 오류를 표시하지 않고 위에서 순서대로 각 Bit를 모두 담은 뒤 그 이상의 Bit가 존재하면 다음 영역을 또 다시 확보하고 해당 Bit를 담게 됩니다.

즉, 처음 a부터 e까지 8Bit(1Byte)에 담고 그 다음 f를 위해 다시 8Bit(char = 1Byte)영역을 확보한 후 처음 Bit부분에 f를 담게 되는 것입니다.(나머지 7bit는 낭비됩니다.)

#include <stdio.h>

main()
{
  struct bitfield{
    unsigned char a : 2;
    unsigned char b : 3;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
  };
 
  struct bitfield bit;
 
  bit.a = 2;
  bit.b = 5;
  bit.c = 1;
  bit.d = 0;
  bit.e = 1;
 
  printf("%d\n", bit.a);
  printf("%d\n", bit.b);
  printf("%d\n", bit.c);
  printf("%d\n", bit.d);
  printf("%d\n", bit.e);
}


각 Bit에 값을 설정하고 해당 값을 확인합니다.


bit field라고 해서 특별히 정해진 구문이 있는것은 아닙니다. 단지 bit field를 선언하는데 구조체의 선언방법을 빌려 선언되는것 뿐이며 구문상의 차이도 몇 Bit의 영역을 차지하는가를 나타내는 : x 형식의 구현부분만 다를 뿐입니다.

때문에 실제 bit filed와 구조체사이에는 그리 큰 차이가 없습니다.

#include <stdio.h>
#include <string.h>

main()
{
  struct bitfield{
    unsigned char a : 2;
    unsigned char b : 3;
    unsigned char c : 1;
    unsigned char d : 1;
    unsigned char e : 1;
   
    char name[10];
    int age;
  };
 
  struct bitfield bit;
 
  bit.a = 2;
  bit.b = 5;
  bit.c = 1;
  bit.d = 0;
  bit.e = 1;
 
  strcpy(bit.name, "youngsoo");
  bit.age = 30;
 
  printf("%d\n", bit.a);
  printf("%d\n", bit.b);
  printf("%d\n", bit.c);
  printf("%d\n", bit.d);
  printf("%d\n", bit.e);
 
  printf("%s\n", bit.name);
  printf("%d\n", bit.age);
}


구조체와 bit field를 동시에 구현합니다.


bit field를 선언할때 몇 Bit를 할당할지에 대한 내용은 생략하고 Data형만 쓰는 경우가 있습니다. 이는 실제 Bit영역을 사용하지 않으면서 Program구조상에 구분영역을 만들어 주는 역활을 수행하기 위함입니다.

또한 Bit를 처음부터 채우지 않고 일정부분 비워둬야 하는 경우에도 자주 쓰이는 방법입니다.

#include <stdio.h>

main()
{
  struct bitfield{
    unsigned char a : 2;
    unsigned char   : 3;
    unsigned char c : 1;
    unsigned char   : 1;
    unsigned char e : 1;
  };
 
  struct bitfield bit;
 
  bit.a = 2;
  bit.c = 0;
  bit.e = 1;
 
  printf("%d\n", bit.a);
  printf("%d\n", bit.c);
  printf("%d\n", bit.e);
}


bit field의 3번째 부터 5번째(이전의 b영역)과 7번째(이전의 d영역)은 사용하지 않습니다. 또한 a와 c, e를 영역별로 구분하도록 합니다.


참고 :
각 Field의 구분은 Program이 아닌 개발자 입장에서 입니다.

1 0