C언어 입문자분이 어려워 하는 것 중에 포인터 다음으로 공용체(union)이 아닌가 싶어요.

union이 어려운 개념이라기 보다는 자주 사용하지 않다보니 책을 보고 학습했을 때는 이해가 되었는데,

막상 사용하려니 헷갈리게 되는 것이죠. 또한, 어디에 사용하는지도 모르겠고 말이죠.


C언어는 어셈블러에 가깝다는 얘기를 한 두번은 들어 보셨을꺼에요.

이런 얘기가 나오는 것은 여러 가지 이유가 있겠지만,

메모리 다루는 방법에서도 어셈블러와 가깝다는 생각을 하게 됩니다.

다른 언어와는 달리 C언어의 변수 타입은 문자열, 숫자로 나눈다기 보다는

변수의 크기를 지정하는 쪽에 가깝습니다. 즉, int 는 4바이트의 변수를, char은 1바이트 변수

이렇게 말이죠.


이전에도 공용체(union)의 쓰임새에 대한 글을 올렸습니다만,

여러 개의 바이트 크기를 가지고 있는 변수를 쪼갤 때 공용체(union)를 사용합니다.


예를 들어 리틀엔디안 시스템에서 4바이트 크기의 int num 변수가 있습니다.

num에서 하위 1바이트의 값만 가지고 오고 싶습니다.

이럴 때는 보통 비트 연산을 합니다. num & 0xff 이런 식으로 말이죠.

만일 하위 두 번째 바이트만 가져 오려면 0xff00 으로 and 연산을 하고 비트를 오른쪽으로 쉬프트하겠죠?


그러나 공용체(union)를 사용하면 매우 간단해 집니다.

int num에 1개 바이트 char 변수 a를 공용체(union)로 묶으면

int num의 최 하위 바이트에 char a 변수를 매칭해 줍니다.


아래 공용체 선언을 보시죠.


union union_t {

    int     num;

    char  a;

}


union_t의 전체 바이트 개수는 몇 개일까요? 정답은 4바이트입니다.

이유는 가장 큰 변수인 int num을 메모리에 항당합니다.

그리고 char a 변수는 num의 메모리의 일부분을 배당합니다.


즉, 아래와 같은 꼴이죠.


image1.png


그러므로 리틀엔디안 시스템에서 num의 하위 바이트는 char a와 같으 메모리를 공유합니다.


union union_t un;


un.num  = 0x01;

un.a      = 0x02;

printf( "un.num=%x\n", un.num);


un.num은 어떻게 출력될까요? 메모리 모양을 보시면 아시겠지만, un.a는 un.num과 메모리를 공유하기 때문에 2로 출력됩니다. 


자, 그렇다면 아래처럼 선언했다면 어떨까요?


union union_t {

    int     num;

    char  a;

    char  b;

    char  c;

    char  d;

}


char a, b, c, d 모두 int num의 영역을 같이 사용할 것입니다. 그렇다면 아래와 같이 


image2.png

이렇게 배치 될까요? 그러나 공용체가 메모리를 공유하기로 되어 있지, 다른 변수와 나란히 배열한다는 내용은 없습니다.

즉, 아래와 같이 메모리가 지정됩니다.


image3.png


이해 되시죠? 그렇다면 아래 코드를 보실까요?


union union_t un;

un.num  = 0x01;

un.a    = 0x02;

un.b    = 0x03;

un.c    = 0x04;

un.d    = 0x05;


printf( "un.num=%x\n", un.num);


자, 마지막 un.num 값은 얼마일까요? 당연히 5 가 출력됩니다.