본문 바로가기
Basic/C/C++

[C언어] 제 21 강 : 구조체, 공용체 그리고 열거형

by boxbop 2012. 1. 27.
반응형


 여러가지 데이터를 하나로 묶기 위해 구조체가 등장하였습니다. 예를 들면 X 좌표와 Y좌표, 가로값과 세로값 그리고 높이값, 이름과 주소, 전화번호, 나이등 연관있는 데이터들을 하나로 묶어서 관리하면 참 편하겠죠~? 소프트웨어 개발 과정에서는 표현하는 데이터들은 그룹으로 관리를 하게됩니다.

 struct MAN
{
    char name[10];
    int age;
 };

 MAN은 구조체의 이름이고 중괄호 안에있는 문장들은 구조체 MAN의 맴버입니다. 이러한 정의가 이뤄지고 난 다음부터 MAN은 변수의 선언에 사용되는 자료형의 이름으로 인식이 됩니다.

 struct MAN boxbop;

 cf) typedef struct MAN MAN; 이라고 추가로 작성하면
      struct MAN boxbop 대신 단순히 MAN boxbop으로 사용할 수 있다.

 이라고 한다면 자료형이 MAN인 새로운 변수 boxbop이 생성됩니다. boxbop 내부에는 name과 age라는 맴버가 존재하겠죠? 그렇다면 이 내부에 있는 맴버변수에 어떻게 접근을 할까요?  .(dot) 연산자를 사용합니다.

 boxbop.age = 10;
 strcpy(boxbop.name, "boxbop");

 변수명.맴버변수 의 형태로 접근을 하게됩니다^-^
그렇다면 이제 포인터의 개념을 조금 적용하여 살펴보도록 하겠습니다.

 MAN boxbop;
 MAN* boxbopPtr;

 boxbopPtr = &boxbop;

 이번엔 포인터 변수도 등장을 했습니다. 포인터 변수는 boxbop의 주소값을 가지고 있군요~ 그렇다면 포인터 변수를 사용하여 boxbop의 맴버변수에 접근하는 방법은 어떻게 해야될까요..? '->' 연산자를 사용합니다.

 구조체 이름에서 접근하는 방법은

boxbop.name
boxbop.age
boxbop.number

 이렇게 '.(dot)' 연산자를 사용합니다.
반면에 포인터를 이용한 구조체 맴버의 접근은

boxbopPtr->name
boxbopPtr->age
boxbopPtr->number

 위와 같이 나타냅니다. 아래와 같은 방법도 옳은 접근방법입니다.

(*boxbopPtr).name
(*boxbopPtr).age
(*boxbopPtr).number


 왜냐하면 (*boxbopPtr)는 boxbop와 동일하기 때문입니다~

 그렇다면 구조체 변수의 선언과 초기화는 어떻게 이루어질까요? 다른 자료형처럼 선언과 동시에 초기화가 가능합니다. 마치 배열의 초기화 방법과 유사합니다. 초기화할 값을 중괄호 안에 쉼표로 구분 지어 표시하면 됩니다.

 struct __person
{
   char name[10];
   char ID[10];
   unsigned int age;
 };
typedef struct __person person;

int mian(void)
{
   person andrew = {"andrew", "anw1234", 10};
 }

 위 예제와 같이 초기화가 이루어 집니다. 간단하죠?

 사실 구조체의 정의 부분에서 typedef 연산을 사용하는 등 조금은 뭔가 불필요한 느낌이 들고 있습니다. 뭔가 좀 더 간단하게 나타낼 방법은 없을까요? 다음 두 예제는 동일합니다.

  struct __person
{
   char name[10];
   char ID[10];
   unsigned int age;
 };
typedef struct __person person;

==>
        
 typedef struct __person
{
   char name[10];
   char ID[10];
   unsigned int age;
 }person;

 구조체는 struct라는 키워드를 사용해서 정의하는 반면, 공용체는 union이라는 키워드를 사용해서 정의합니다. 외관상 차이점은 그게 다입니다.

  typedef union __number
{
   char str;
   int number;
   double dnumber;
 }num;

 그러나 각각의 변수가 메모리 공간에 할당되는 방식과 접근방식에는 많은 차이가 있습니다. 구조체는 각각의 맴버 변수에 개별적인 공간이 할당되지만 공용체 변수는 맴버 중에서 크기가 가장 큰 맴버의 바이트만큼만 메로리 공간이 할당됩니다. 위에서는 double형이 가장 크므로 8바이트만 할당이 되겠죠~?

 공용체의 유용함은 다양한 접근방식을 제공하는데 있습니다. 8바이트를 할당받지만 8바이트를 char형, int형, double형으로 모두 사용이 가능합니다. 

 사용자로부터 int형 데이터를 하나 입력받아서 입력 받은 정수의 상위, 하위 2바이트씩 나누어 출력하고, 최상위 1바이트와 최하위 1바이트 저장된 값을 출력하는 프로그램을 작성해야된다고 한다면 이럴때 공용체가 아주 유용하게 사용됩니다. 뭔가 자잘하게 나눈다는 느낌 안드나요~?ㅋㅋㅋ 다음 예제를 보시고 대충 그까이꺼 이해해보세요

 typedef struct __updownshort
{
   unsigned short up;
   unsigned short lower;
 }udshort;

 typedef union __number
{
   int i;
   char c[4];
   udshort s;
 }number;

int main (void)
{
   number buf;
   buf.i=13451345;

   buf.s.up;
   buf.s.down;
   buf.c[0];
   buf.c[3];
 
   return 0;
 }

 따로 설명하지는 않겠습니다. 진하게 표시되어 있는 부분이 중요하다는 뜻 입니다^-^ 열거형도 구조체나 공용체와 마찬가지로 자료형을 정의하는 방법입니다.

 enum value
 {
     A = 1, B = 2, C = 3, D = 4
 };

==>

typedef enum __value
{
    A = 1, B = 2, C = 3, D = 4
}value;

 A를 상수 1로 정의합니다. 마찬가지로 B, C, D는 2, 3, 4로 정의되구요~ 열거형은 솔직히 별거 없네요....ㅋㅋㅋ 즉 A, B, C, D라는 이름의 상수를 각각 1, 2, 3, 4로 정의하고, 이 값들을 value형 변수가 저장할 수 있는 값들로 제한합니다.

 구조체, 공용체, 열거형 모두 정의하면서 동시에 변수를 선언하는 것이 가능합니다. 

 struct point
{
   int x;
   int y;
 }p1, p2;   -> 변수 p1, p2가 생성

 enum number

   A, B, C
 }num; -> 변수 num이 생성

 그리고 자료형의 이름도 생략할 수 있습니다. 사실상 열거형은 자료형의 이름을 자주 생략해서 사용하곤 합니다^-^

 struct
{
   int x;
   int y;
 }p1, p2;

 enum

   A, B, C
 }num; 

 p1.x =1; 이나 num = A와 같은 코드를 작성해 볼 수 있겠죠? 오늘은 여기까지 하도록 하겠습니다. C언어가 거의 마무리 되가네요~ 앞으로 1~2장 정도만 복습하면 끝날 듯 싶습니다~~!!!! 으 지겨워 그 다음엔 C++에 대해서 복습할껀대요 다른 과목들도 같이 복습을 병행해 나갈거라 아주 간단간단하게 설명할 것 같습니다ㅠ 이만 마치도록 하겠습니다(--)(__)(--)!!!
   
 

반응형