1. 공용체(union)


저번 편에선 구조체에 대해서 알아보았는데 이번에 배울 공용체(union)란 뭘까요? 공용체는 말 그대로, 같은 메모리 공간을 여러개의 변수가 공유하며, 공용체를 선언하여 사용하는 방법은 구조체와 매우 유사합니다. 그러나 주의하셔야 할 부분은 구조체의 메모리 운영방식과 공용체의 메모리 운영방식은 서로 다릅니다. 공용체는 어떻게 메모리를 잡아먹는지 간단히 살펴보도록 합시다.

 
위의 그림을 보시면 이들의 시작주소는 모두 같으며 하나의 메모리 공간을 두개의 변수가 사용하고 있습니다. 좀더 확실한 이해를 위해 예제를 살펴보면서 공용체가 어떤 녀석인지 이해를 하도록 합시다.

#include <stdio.h>

union intbox {
      int a;
      int b;
};

int main()
{
    union intbox n;
    
    n.a=1;
    printf("n.a:%d\nn.b:%d\n", n.a, n.b);
    return 0;
}
결과:

n.a:1
n.b:1
계속하려면 아무 키나 누르십시오 . . .


예제를 보시면, 3~6행에서 공용체 intbox를 정의하고 10행에서 공용체 변수 n를 선언하여 n의 멤버인 a에 접근하여 1이란 숫자를 저장했습니다. 그런데 이게 무슨일일까요? n.a만 아니라 n.b의 값도 바뀌었습니다. 왜냐하면 공용체 자체의 특징상 하나의 메모리 공간을 두 변수가 공유하여 사용하고 있기 때문입니다. 아직 이해가 잘 가지 않으신다구요? 그럼 아래의 예제를 하나 더 보도록 합시다.

#include <stdio.h>

union readBuf
{
   unsigned int a;
   unsigned short b;
   unsigned char c;
};

int main()
{
   union readBuf variable;
   variable.a = 0x12345678;

   printf("%x\n",variable.a);
   printf("%x\n",variable.b);
   printf("%x\n",variable.c);
  
   return 0;
}

결과:

12345678
5678
78
계속하려면 아무 키나 누르십시오 . . .


왜 결과물이 다음과 같이 출력되었을까요? 이는 int 형이 주어진 4바이트를 모두 사용하고 short 형은 상위 2바이트를, char형은 상위 1바이트를 사용하기 때문입니다. 또 다르게 사용하여 상위 2바이트와 하위 2바이트를 출력할 수 있습니다. 차근차근 생각하여보면, 0x12345678은 16진수이므로 10진수로 바꾸어주면 305419896이고, 이걸 다시 2진수로 바꾸어 주면 10010 00110100 01010110 01111000(2)와 같습니다.


이렇게 되면 variable.a는 305419896(16진수로 12345678), variable.b는 상위 2바이트를 모두 사용하므로 22136(16진수로 5678), variable.c는 상위 1바이트를 모두 사용하므로 120(16진수로 78)이란 결과가 나오는 것입니다. 참고로 공용체의 크기는 공용체 내에서 자료형의 크기가 가장 큰 자료형을 기준으로 결정이 됩니다. 위의 예제에서 readBuf는 제일 큰 자료형이 int형이므로, 크기는 4바이트가 됩니다. 이해 되시나요?


2. 열거형(Enumerated Types)


열거형이란 또 뭘까요? 변수가 가질수 있는 값들을 나열, 즉 정수형 상수들로 구성되는 자료형을 말합니다. 열거형을 사용하면 가독성이 향상되며 기억하기가 상당히 쉽습니다. 열거형의 선언방법은 아래와 같이 enum이란 키워드를 사용하여 선언할 수 있습니다.

enum 열거형이름 {
  열거 멤버;
};

여기서 열거 멤버는 값의 이름이 차례대로 나열되며, 값을 따로 지정해주지 않으면 왼쪽부터 차례대로 0부터 시작하여 값이 증가합니다. (열거 멤버는 값을 지정해주지 않으면 앞의 멤버의 값에 1을 더한 값을 가집니다.)


#include <stdio.h> 

int main()
{
   enum Days{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};

   Days TheDay;
   int j = 0;
   printf("요일을 입력하세요. (0과 6사이)\n");
   scanf("%d",&j);
   TheDay = Days(j);

   if(TheDay == Sunday || TheDay == Saturday)
    printf("만세! 그것은 주말입니다.\n");
   else
    printf("젠장, 여전히 근무한다!\n");

   return 0;
}

결과:
요일을 입력하세요. (0과 6사이)
6
만세! 그것은 주말입니다.
계속하려면 아무 키나 누르십시오 . . .


여기서 상수 식별자는 0부터 순서대로 정수값이 부여된다는 사실을 기억하셔야 합니다. 그렇다면 Sunday(0), Monday(1), Tuesday(2), Wednesday(3), Thursday(4), Friday(5), Saturday(6). 5행에서 열거형 변수 Days를 정의하고 7행에서 TheDays를 선언했습니다. 그리고 사용자로부터 값을 입력받고 토요일이거나 일요일일 경우엔 "만세! 그것은 주말입니다"가 출력되며 월~금때는 "젠장, 여전히 근무한다!"가 출력되게 됩니다.


열거형에서 확실히 알아두실게 있다면, 앞에서 "열거 멤버는 값을 지정해주지 않으면 앞의 멤버의 값에 1을 더한 값을 가집니다."라는 말을 했었는데 그렇다면 아래의 경우에서 APPLE은 어떠한 값을 가질까요?

enum word {AIRPLANE = 1, PIZZA, APPLE = 4, BANANA};

AIRPLANE은 1의 값을, PIZZA는 앞의 열거 멤버의 값에 1을 더한 값인 2를, APPLE은 4의 값을, BANANA는 앞의 열거 멤버의 값에 1을 더한 값인 5를 가집니다. 간단하죠?