IT 과학/C언어

C언어 | 구조체와 공용체

곰뚱 2020. 1. 27.

 

 

 

C 언어에서는 char, int, double 등의 기본적인 데이터형 이외에도 더욱 복잡한 데이터형을 사용자가 정의하는 것이 가능하다. 그것은 구조체, 공용체라고 불려지는 것으로, 다른 종류의 데이터들을 한 덩어리의 데이터로서 다룰 수 있다. 본 내용에서는 구조체란 무엇인가를 먼저 설명하고 구조체 배열, 구조체에의 포인터 등에 관해서도 설명한다. 그리고 공용체와 그 이용법에 관해서도 설명한다.

 

 

1. 구조체란?

(1) 레코드형 데이터

표 1의 데이터는 갈릴레오가 1610년에 발견한 목성의 4대 위성의 위성명, 고도, 주기에 관한 것이다.

 

위성명(name)

광도(luminosity)

주기(period)

Io

5

1.1691

Europa

6

3.5512

Ganymede

5

7.1545

Callisto

6

16.6890

표 1 목성의 4개의 위성

 

이러한 데이터는 한 위성의 위성명, 광도, 주기를 한 집단의 데이터로 취급하면 편리하다. 이와 같이 몇 개의 항목을 한 집단으로 한 것을 레코드(record)라 부르며, 각 항목을 필드 (field)라고 부른다. 구조체는 이와 같은 레코드를 정의하는 것이다.

 

(2) 구조체의 선언

표 1을 구조체의 데이터로 하기 위해서는 각 필드형과 필드명을 결정해야 한다. 위성명은 영문 첫 자(char 형)의 I, E, G, C로 표시하고 필드명을 name이라고 하자. 광도는 int 형으로 필드명을 luminosity라 하자. 주기는 double 형으로 필드명을 period라고 하자. 그리고 name, luminosity, period를 세 개의 필드로 갖는 레코드를 satellite 라 부르자. 이와 같은 데이터를 구조체로 선언하면 다음 예와 같다.

 

      struct satellite {
          char name;
          int luminosity;
          double period;
      } ;

 

이렇게 함으로써 struct satellite 형이라는 새로운 형(구조체형)이 선언된다. 즉, satellite는 char, int, double형을 필드로 하는 새로운 형의 이름으로 이것을 태그(tag)라 부른다.

 

구조체의 변수를 선언하는데는 태그를 사용해서

 

struct satellite a;

 

라고 표시한다. 이것으로 satellite 형의 구조체 변수 a가 선언된다.

또는 다음과 같이 satellite 형의 태그 선언과 구조체 변수 a의 선언을 같이 해도 된다.

 

      struct satellite {
       char name;
       int luminosity;
       double period;
    } a;

 

(예) 구조체 type 선언

        struct person {
                char name[50];
                short age;
                char phone[20];
        };

        main()
        {
                struct person x;
                static struct person y = { "이효리", 20, "123-4567" };

                strcpy(x.name, "이쵸리"); /* x.name = "이쵸리"; 라고 하면 에러*/
                x.age = 21;
                strcpy(x.phone, "234-5678");
                ......
        }

 

(3) 구조체의 참조

구조체 변수의 각 필드를 참조하는데는 연산자(. )를 사용해서

 

구조체 변수명.필드명

 

라고 표시한다. 예로 위성 Io의 데이터를 구조체 변수 a 에 대입시키려면 다음과 같이 하면 된다.

 

a.name = 'I';
a.luminosity = 4;
a.period = 1.7691;

 

또 이 데이터를 화면으로 출력하려면 다음과 같이 하면 된다.
 

printf("%c %d %f\n", a.name, a.luminosity, a.period);

 

확인문제 1

/* 구조체 멤버가 배열일 때 문자열을 초기화 하는 프로그램의 예 */
#include <stdio.h>
void main(void)
{
      struct address{
          char name[10];
          char *add;
          char tel_num[14];
          char value[5];
          int  data[3];
          int   result;
      };
      int i;
      char spt[11] = "Kang Nung";
      struct address x = {"Jung S.M", spt, '0', '6', '6', '1', '-', '7','4','4','-',
                          '5', '3', '2', '2','\0', {'O', 'K','\0'}, 5, 15, 20, 1234};

      printf("%s\n", x.name);
      printf("%s\n", x.add);
      printf("%s\n", x.tel_num);
      printf("%s\n", x.value);
      printf("%d\n", x.result);
      for( i = 0; i < 3; i++)
          printf("%d ", x.data[i]);
}

 

(4) 구조체의 대입

K&R C는 구조체의 대입을 할 수 없지만 ANSI 규격안에 준한 Turbo C등의 컴파일러에서는 이것을 인정하고 있다. 즉, 앞에서 구조체 변수 a 와 동일한 형의 구조체 b를

 

struct satellite b;

 

라고 선언하면

 

b = a;

 

에 의하여 a의 내용이 b에 대입되므로 b.name은 I, b.luminosity는 5, b.period 는 1.7691이 된다.

 

확인문제 2

/* 구조체 변수간의 대입 연산을 수행하는 프로그램 예제 */
#include <stdio.h>
void main(void)
{
      struct personnel
      {
        char name[30];
        int code;
      };

      struct personnel person1, person2;

      printf("\nperson 1.\nEnter name : ");
      gets(person1.name);
      printf("Enter person code (3 digits) : ");
      scanf("%d", &person1.code);

      person2 = person1;

      printf("\nList of persons:\n");
      printf("Person1 name: %s\n",  person1.name);
      printf("Person1 code: %3d\n", person1.code);
      printf("Person2 name: %s\n",  person2.name);
      printf("Person2 code: %3d\n", person2.code);
}

728x90

 

 

2. 구조체 배열

구조체 배열도 인정되고 있다. 앞에서 태그 satellite를 사용해서
      

struct satellite a[10];

 

라고 하면, satellite 형의 구조체 배열 a[0], a[1], …a[9]가 준비되며 각 요소에 대한 참조는 다음과 같다.

 

a[0].name = 'I';
a[0].luminosity = 5;
a[0].period = 1.7691;
a[1].name = 'E'; ...
          

 

또한, 구조체 배열을 사용하면 다음과 같이 초기화된다.

 

struct satellite a[ ]={{'I', 5, 1.7691},
                               {'E', 6, 3.5512},
                               {'G', 5, 7.1545},
                               {'C', 6, 16.6890}};

 
예제 1. 표 1의 데이터를 구조체 배열로 초기화하여 화면에 표시하여라.

● 프로그램
 #include <stdio.h>
 main( )
 {
         int k;
         struct satellite {
             char name;
             int luminosity;      
             double period;
         } ;
         struct satellite a[]={{'I', 5, 1.7691},
                                       {'E', 6, 3.5512},
                                       {'G', 5, 7.1545},
                                       {'C', 6, 16.6890}};
         for (k = 0; k < 4; k++)   
             printf("%c%3d%8.4f\n",a[k].name, a[k].luminosity, a[k].period);
 }

●  결과
 I  5   1.7691
 E  6   3.5512
 G  5   7.1545
 C  6  16.6890


(예) 구조체 배열을 직접 선언한 예

        main()
        {
                struct person {
                        char *name;
                        short age;
                        char *phone;
                } singer, man[10], woman[20];

                man[0].name = "Lee Hyolee";
                man[0].age = 24;
                man[0].addr = "02-345-6789";
                ......
        }

 

<참고> 중첩된 구조체 (nested structure)

        struct address {
                char *nation;
                char *city;
                char *zipcode;
        };

        struct person {
                char *name;
                short age;
                char *phone;
                struct address addr;
        };

        main()
        {
                struct person singer;

                singer.name = "Hyolee";
                singer.age = 24;
                singer.addr.nation = "Korea";
                singer.addr.city = "서울";
                .......
        }

 


확인문제 3

/* 중첩된 구조체를 사용하는 예제 프로그램 */
#include <stdio.h>
void main(void)
{
      struct personnel
      {
        char name[30];
        int code;
      };
      struct group
      {
        struct personnel chief;
        struct personnel member;
      };

      struct group group1 = {{"Lee Hyolee", 999}, {"Sung Yoori", 700}};
      struct group *sp = &group1;

      printf("\n      Chief:\n");
      printf("       Name: %s\n", group1.chief.name);
      printf("code number: %d\n", group1.chief.code);
      printf("\n     Member:\n");
      printf("       Name: %s\n", sp->member.name);
      printf("code number: %d\n", sp->member.code);
}

 

 

3. 구조체에 대한 포인터

구조체에도 포인터를 사용할 수 있다. 앞의 태그 satellite를 사용해서

 

struct satellite *p;

 

라고 선언하면, p가 구조체의 포인터 변수가 된다. 이 포인터 변수 p에 앞의 구조체 배열 a[ ] 의 선두 주소는 다음에 의해 전달된다.

 

p = a;

 

이렇게 하면 포인터 변수 p를 사용해서 다음과 같이 구조체 배열 a[ ]를 참조할 수 있다.

즉, p->name에 의하여 a[0].name, p->luminosity에 의하여 a[0].luminosity, p->period에 의하여 a[0].period를 참조한다.

일반적으로 포인터에 의하여 지시되어 있는 구조체의 각 필드를 참조하기 위해서는 연산자 ->를 사용해서

 

포인터 변수명->필드명

 

라고 쓴다. 그러면, 포인터 변수 p를

 

p++;

 

라고 하면 이 때의 p->name, p->luminosity, p->period는 각각 a[1].name, a[1].luminosity, a[1].period와 같은 데이터를 지정하게 된다.

 

예제  2. 표 1의 데이터 주기값을 입력해서 내림차순으로 정렬하는 함수 sort를 작성하여라.

● 프로그램
 #include <stdio.h>
 struct satellite {      /* ① */
      char name;  
      int luminosity;
      double period;
  };
  main( )
  {
       int k;
       struct satellite a[]={{'I', 5, 1.7691},
                                     {'E', 6, 3.5512},
                                     {'G', 5, 7.1545},
                                     {'C', 6, 16.6890}};
       sort(a, 4);      /* ② */
       for (k = 0; k < 4 ; k++)
          printf("%c%3d%8.4f\n", a[k].name, a[k].luminosity, a[k].period);
  }
  sort(b, n)
  struct satellite b[];       /* ③ */
  int n;
 {
        int k, i, s;
        double max;
        struct satellite dumy;
        for (k = 0; k < n-1; k++){
           max = b[k].period;
           s = k;
           for (i = k +1; i< n; i++) {
              if (b[i].period > max) {
                 max = b[i].period;
                 s = i;
              }
           }
           dumy = b[k]; b[k] = b[s]; b[s] = dumy;     /* ④ */
       }
  }

● 해설
① 함수 sort도 struct satellite 형을 사용하므로 외부 선언을 해 둔다.
② 구조체 배열 a[] 의 선두 주소와 요소 수를 전달한다.
③ 형식인수는 struct satellite 형으로 포인터를 이용하여 선언한다. 포인터 b에 연산자 []를 붙여 배열을 했을 경우 필드 참조는 b[0].period 등으로 한다. 포인터 b만을 참조할 때는 b->period 라고 한다.
④ ANSI C를 따르는 Turbo C 에서는 구조체의 대입이 가능하다.
 
●  결과
 C  6   16. 6890
 G  5    7. 1545
 E  6    3. 5512
 I  5     1. 7691

※ ANSI C 형태의 프로그램으로 변환하여 볼 것!


(예) 구조체 pointer


        #include <stdio.h>

        struct person {
                char name[50];  /* char *name; 선언, p->name = "name"; */
                short age;
                char phone[20]; /* char *phone; 선언하면, p->phone = "..."; */
        };

        main()
        {
                struct person prisoner = { "Princess", 65, "molla" };
                struct person *p = &prisoner;

                strcpy(p->name, "백설공주");
                strcpy(p->phone, "629-1212");

                printf("공주병을 퍼뜨린 %s는 벌을 받아야 한다.\n", p->name);
        }

   
확인문제 4

/* 구조체에 접근하기 위한 간접 멤버 참조 연산자('->')의 예제 */
#include <stdio.h>
struct data
{
      int num;
      char name[10];
};

void main(void)
{
      int i;
      struct data sum;
      struct data array[3], *sp1, *sp2;
      sp1 = &sum;
      sp2 = array;
      printf("Input number and name : ");
      scanf("%d  %s", &sum.num, sum.name);
      for(i = 0; i < 3; i++)
      {
          printf("Input number and name : ");
          scanf("%d", &(sp2 + i)->num);
          gets((sp2 + i)->name);
      }
      printf("%d   %s\n", sp1->num, sp1->name);
      for(i = 0; i < 3; i++)
      {
          printf("%d  %s\n", (*(sp2 + i)).num, (*(sp2 + i)).name);
      }
}

 

(1) 구조체 변수의 인수 전달

        #include <stdio.h>

        struct person {
                char name[50];
                short age;
                char phone[20];
        };

        main()
        {
                struct person x = { "이효리", 24, "molla" };

                f(x);   /*   f(&x); */
                printf("그의 나이는 %d살이다.\n", x.age);
        }

        f(y)                        |     f(y)
        struct person y;      |     struct person *y
        {                           |     {
                y.age++;        |           y->age++;
        }                           |     }

 

확인문제 5

/* 구조체 멤버를 사용한 값에 의한 함수 호출의 예제 프로그램 */
#include <stdio.h>
struct person
{
      int number;
      char *name;
      struct course
      {
          int cobol;
          int fortran;
          int basic;
      } lan;
      int total;
      double average;
};
int sum(int, int, int);
void main(void)
{
      struct person data = {101, "Kim", 90, 80, 75, 0, 0.0};

      printf("number: %d  Name: %s\n", data.number, data.name);
      data.total= sum(data.lan.cobol, data.lan.fortran, data.lan.basic);
      data.average = data.total / 3.0;
      printf("%3d %8d %8d\n\n", data.lan.cobol, data.lan.fortran, data.lan.basic);
      printf("total:  %3d  average: %.2lf\n", data.total, data.average);
}

int sum(int a, int b, int c)
{
      printf("cobol   fortan   basic\n");
      printf("----------------------\n");
      return(a + b + c);
}

 

확인문제 6

/* 구조체 멤버를 사용한 참조에 의한 함수 호출의 예제 프로그램 */
#include <stdio.h>
struct person
{
      int number;
      char *name;
      struct course
      {
          int cobol;
          int fortran;
          int basic;
      } lan;
      int total;
      double average;
};
int sum(int *, int *, int *);
void main(void)
{
      struct person data = {101, "Kim", 90, 80, 75, 0, 0.0};

      printf("number: %d  Name: %s\n", data.number, data.name);
      /* 구조체 멤버의 참조에 의한 호출(멤버에 주소 연산자 사용) */
      data.total = sum(&data.lan.cobol, &data.lan.fortran, &data.lan.basic);
      data.average = data.total / 3.0;
      printf("%3d %8d %8d\n\n", data.lan.cobol, data.lan.fortran, data.lan.basic);
      printf("total:  %3d  average: %.2lf\n", data.total, data.average);
}

int sum(int *a, int *b, int *c)
{
      printf("cobol   fortan   basic\n");
      printf("----------------------\n");
      return(*a + *b + *c);
}

 

확인문제 7

/* 구조체 변수를 사용한 값에 의한 함수 호출의 예제1 */
#include <stdio.h>
struct person
{
      int number;
      char *name;
      struct course
      {
          int cobol;
          int fortran;
          int basic;
      } lan;
      int total;
      double average;
};
int sum(struct person);
void main(void)
{
      struct person data = {101, "Kim", 90, 80, 75, 0, 0.0};

      printf("number: %d  Name: %s\n", data.number, data.name);
      data.total = sum(data);
      data.average = data.total / 3.0;
      printf("%3d %8d %8d\n\n", data.lan.cobol, data.lan.fortran, data.lan.basic);
      printf("total:  %3d  average: %.2lf\n", data.total, data.average);
}

int sum(struct person temp)
{
      printf("cobol   fortan   basic\n");
      printf("----------------------\n");
      return(temp.lan.cobol + temp.lan.fortran + temp.lan.basic);
}

 

확인문제 8

/* 구조체 변수를 사용한 값에 의한 함수 호출의 예제2 */
#include <stdio.h>
struct person
{
      int number;
      char *name;
      struct course
      {
          int cobol;
          int fortran;
          int basic;
      } lan;
      int total;
      double average;
};

struct person sum(struct person);
void main(void)
{
    struct person data = {101, "Kim", 90, 80, 75, 0, 0.0};
    struct person result;

    printf("number: %d  Name: %s\n", data.number, data.name);
    result = sum(data);
    printf("%3d %8d %8d\n\n", result.lan.cobol, result.lan.fortran, result.lan.basic);
    printf("total:  %3d  average: %.2lf\n", result.total, result.average);
}

struct person sum(struct person temp)
{
    printf("cobol   fortan   basic\n");
    printf("----------------------\n");
    temp.total = temp.lan.cobol + temp.lan.fortran + temp.lan.basic;
    temp.average = temp.total / 3.0;
    return(temp);
}

 

확인문제 9

/* 구조체 배열을 함수의 전달 인수로 사용하는 참조에 의한 함수 호출 */
#include <stdio.h>
struct person
{
      int number;
      char *name;
      struct course
      {
          int cobol;
          int fortran;
          int basic;
      } lan;
      int total;
      double average;
};
void  sum(struct person*);
void main(void)
{
      int  i;
      struct person data[3] = {{101, "Kim",  90,  80,  75, 0, 0.0},
                             {102, "Jung", 99,  87,  88, 0, 0.0},
                             {103, "Park", 76,  94,  78, 0, 0.0}};
      sum(data);
      for(i = 0; i < 3; i++)
      {
          printf("number: %d  Name: %s\n", data[i].number, data[i].name);
          printf("cobol   fortan   basic\n");
          printf("----------------------\n");
          printf("%3d %8d %8d\n\n", data[i].lan.cobol, data[i].lan.fortran, data[i].lan.basic);
          printf("total:  %3d  average: %.2lf\n\n", data[i].total,
                   data[i].average);
      }
}

void sum(struct person *temp)
{
      int i;
      for(i = 0; i <3; i++)
      {
          temp[i].total = temp[i].lan.cobol + temp[i].lan.fortran + temp[i].lan.basic;
          temp[i].average =temp[i].total / 3.0;
      }
}

 

(2) 구조체 list와 자기 참조 구조체

        #include <stdio.h>
        struct person {
                char name[50];
                short age;
                char phone[20];
                struct person *next;
        };

        struct person x = { "이효리", 22, "518-1212", NULL },
                             y = { "성유리", 20, "629-1212", NULL },
                             z = { "옥주현", 21, "444-4444", NULL };
        main()
        {
                struct person *head, *p;

                /* make a LIST */
                head = &x;
                x.next = &y;
                y.next = &z;

                p = head;
                while (p) {
                        printf("%s\n", p->name);
                        p = p->next;
                }
        }

 

확인문제 10

/* 구조체 포인터 변수의 사용 */
#include <stdio.h>
void main(void)
{
      struct list
      {
          int num;
          char ch;
      };

      struct list data;
      struct list *pt;

      pt = &data;
      pt->num = 333;
      pt->ch  = 'A';
      printf("pt->num = %d, pt->ch = %d\n", pt->num, pt->ch);
}


확인문제 11

/* 선형 연결 리스트의 구성과 사용의 예 */
#include <stdio.h>

struct list
{
      char ch;
      int num;
      struct list *pt;
};

void main(void)
{
      struct list a = {'a', 111, NULL}, b = {'b', 222, NULL},
                c = {'c', 333, NULL}, *head;

      a.pt = &b; b.pt = &c;
      for(head = &a; head != NULL;  head = head->pt)
      {
        printf("%c ===> ", head->ch);
        printf("%4d\n", head->num);
      }
}

 

확인문제 12

/* malloc( ) 함수의 사용의 예 */
#include <stdio.h>
#include <alloc.h>
void main(void)
{
      struct list
      {
          int num;
          struct list *next;
      };
      struct list *spt;
      int *pt, i;
      float *x;

      pt = (int *)malloc(4 * sizeof(int));
      x = (float *)malloc(2 * sizeof(float));

      *pt = 11;
      *(pt + 1) = 22;
      *(pt + 2) = 33;
      *(pt + 3) = 44;

      *x = 0.234;
      *(x + 1) = 3.14;

      printf("%5d %5d %5d %5d\n", *pt, *(pt + 1), *(pt + 2), *(pt + 3));
      printf("%5.3f %5.3f\n", *x, *(x + 1));
      printf("sizeof(struct list) = %d bytes.\n", sizeof(struct list));

      for(i = 0; i <= 3; i++)
      {
        spt = (struct list *)malloc(sizeof(struct list));
        printf("spt = %#x\n", spt);
      }
}

 

확인문제 13

/* malloc( ) 함수와 자기 참조 구조체의 사용한 기본 연산의 예 */
#include <stdio.h>
#include <alloc.h>
void main(void)
{
      struct list
      {
        int num;
        struct list *next;
      };
      struct list *spt;

      spt = (struct list *)malloc(sizeof(struct list));
      spt->num = 111;
      spt->next = NULL;
      printf("spt = %#x, &(spt->num) = %#x\n", spt, &(spt->num));
      printf("spt->num = %d\n", spt->num);
}

 

확인문제 14

/* malloc( ) 함수와 자기 참조 구조체의 사용한 연결 리스트 구성 */
#include <stdio.h>
#include <alloc.h>
struct list
{
      int num;
      struct list *next;
};
int input(void);
void main( )
{
      int i;
      struct list *head, *pt;

      /* 연결 리스트의 첫번째 구조체의 할당 */
      if((head = (struct list *)malloc(sizeof(struct list))) == NULL)
      {
          printf("Dynamic memory allocation Error!\n");
          exit(1);
      }
      else
      {
          head->num = input( );
          head->next = NULL;
          pt = head;

          /* 3개의 구조체를 할당하여 연결 리스트에 연결 시킴 */
          for( i = 1; i <= 3; i++)
          {
              if((pt->next = (struct list *)malloc(sizeof(struct list))) == NULL)
              {
                  printf("Dynamic memory allocation Error!\n");
                  exit(1);
              }
              pt->next->num = input( );
              pt = pt->next;
          }
          pt->next = NULL;
      }
      /* 연결 리스트를 순회하여 각 구조체의 멤버 num에 저장된 데이타 출력 */
      while(head != NULL)
      {
          printf("head->num = %d \n", head->num);
          head = head->next;
      }
}

int input(void)
{
      int data;

      printf("Input data: ");
      scanf("%d", &data);
      return(data);
}

 

 

4. 공용체

일반 변수는 그 형이 선언되면 그 형만 그 변수에 사용할 수 있다. 그러나 공용체를 사용하면 다른 형을 동일 변수에 넣어서 사용할 수 있다. 공용체의 선언은 예약어 union을 사용해서 다음과 같이 한다. 공용체의 선언 방법, 참조의 방법은 구조체의 경우와 동일하다.

 

union body {
         char a;
        int b;
          long c;
        }  dat;

 

위와 같이 하면 공용체 변수 dat가 선언된다.

공용체 변수 dat 내에는 dat.a, dat.b,  dat.c 와 같이 작은 영역으로 나뉘어지며, dat.a에는 char 형의 데이터, dat.b에는 int 형의 데이터, dat.c에는 long 형의 데이터를 넣는 것이 된다. 여기서 주의하여 생각할 것은 각 상자는 그 것보다 더 작은 상자를 포함하고 있어서 3개의 작은 상자는 독립된 것이 아니므로 어떤 하나의 데이터를 넣으면 다른 상자의 데이터는 그 시점에서 파괴되어 버린다. 예를 들어

 

dat.a = 'A';

 

라고 하면 공용체 변수 dat에 'A'가 들어가고

 

dat.b = 10;

 

라고 하면 공용체 변수 dat에 10이 들어가게 된다. 즉, 앞에서 넣었던 'A'는 지워지게 된다.

공용체의 구체적인 예로 CPU의 레지스터에 데이터를 전달하는 공용체를 생각해 보자. 8086의 범용 레지스터는 16비트 AX, BX, CX, DX가 있으며 이 레지스터들은 8비트 레지스터 AH, AL, BH, BL, ... 로서도 사용할 수 있다.

Turbo C에서는 이와 같은 공용체를 dos.h 내에서 다음과 같이 정의하고 있다.

          struct WORDREGS {
                 unsigned int ax, bx, cx, dx, si, di, cflag, flags;};
          struct BYTEREGS {
                 unsigned char al, ah, bl, bh, cl, ch, dl, dh;};
          union REGS {
                struct WORDREGS x;
                struct BYTEREGS h;};

이와 같이 정의된 union REGS 형을 사용해서 공용체 변수 inregs를 선언할 때는 다음과 같다.

 

union REGS inregs;

 

이와 같이 표현하면 공용체 변수 inregs가 준비된다.

공용체의 필드는 WORDREGS 형의 x와 BYTEREGS 형의 h로 구성된다. 또 구조체 WORDREGS 형 필드는 ax, bx, ...로 구성되고 구조체 BYTEREGS 형 필드는 al, ah, ...로 구성되어 있다.

따라서

 

inregs h.al;

 

라고 하면, al이 참조되고,

 

inregs x.ax;

 

라고 하면 ax가 참조된다.

이와 같은 공용체를 사용하여 MS-DOS의 BDOS (인터럽트 함수 호출)을 실행하기 위한 표준 함수 intdos가 있다.

 

확인문제 15

/* 공용체 변수의 멤버 접근의 예 */
#include <stdio.h>
void main(void)
{
      union tag
      {
        char  ch;
        int    i;
        long   k;
        double x;
      };
      union tag data, num, *pt;

      printf("sizeof(union tag) = %d\n", sizeof(union tag));
      printf("sizeof(data.ch) = %d\n", sizeof(data.ch));
      printf("sizeof(data.i)  = %d\n", sizeof(data.i));
      printf("sizeof(data.k)  = %d\n", sizeof(data.k));
      printf("sizeof(data.x)  = %d\n", sizeof(data.x));

      data.ch =  'A';
      printf("data.ch = %c\n", data.ch);
      printf("data.i  = %d\n", data.i);
      printf("data.k  = %ld\n", data.k);
      printf("data.x  = %lf\n", data.x);

      pt = &num;
      pt->ch = 'a';
      printf("pt->ch = %c\n", pt->ch);
      printf("pt->i  = %d\n", pt->i);
      printf("pt->k  = %ld\n", pt->k);
      printf("pt->x  = %lf\n", pt->x);
}

 

확인문제 16

/* 공용체 변수의 데이타의 word, byte 단위 접근의 예 */
#include <stdio.h>
void main(void)
{
      union
      {
        unsigned long long_int;
        unsigned char ch[4];
        unsigned int  array[2];
      } data;

      data.long_int = 0x12345678;

      printf("data = %#lx\n", data.long_int);
      printf("array[0] = %#x, array[1] = %#x\n", data.array[0], data.array[1]);
      printf("ch[0] = %#x, ch[1] = %#x ch[2] = %#x, ch[3] = %#x\n",
            data.ch[0], data.ch[1],data.ch[2], data.ch[3]);
}

확인문제 17

/* 구조체의 멤버로서 사용된 공용체의 예 */
#include <stdio.h>
void main(void)
{
      struct operation
      {
        long result;
        int type;
        union
        {
            unsigned long value;
            unsigned int  array[2];
            unsigned char ch[4];
        } data;
      };
      struct operation four;

      four.data.value = 0x12345678;
      printf("Choice operation(1-3): ");
      scanf("%d", &four.type);
      switch(four.type)
      {
        case 1:  four.result = four.data.value;
                 break;
        case 2:  four.result = four.data.array[0] + four.data.array[1];
                 break;
        case 3:  four.result = four.data.ch[0] + four.data.ch[1] +
                               four.data.ch[2] + four.data.ch[3];
                 break;
      }
      if(four.type > 3)
        printf("Operation Error!!\n");
      else
        printf("four.result = %#lx\n", four.result);
}

 

확인문제 18

/* 공용체의 멤버로서 사용된 구조체의 예 */
#include <stdio.h>
struct out_campus
{
      char city[10];
      char home_address[20];
};
struct in_campus
{
      char college[10];
      char dorm_name[10];
};
union address
{
      struct out_campus home;
      struct in_campus  dorm;
};
struct student
{
        int    number;
        char   name[10];
        int    type;
        union  address home_dorm;
};

void home_dorm(union address *, int);
int input(struct student *);
void main(void)
{
        struct student data[10];
        int i, count;

        count = input(data);
        for( i = 0; i < count; i++)
        {
            putchar('\n');
            if(data[i].type == 1)
            {
                printf("number   : %d\n", data[i].number);
                printf("name     : %s\n", data[i].name);
                printf("city     : %s\n", data[i].home_dorm.home.city);
                printf("address  : %s\n", data[i].home_dorm.home.home_address);
                putchar('\n');
            }
            else
            {
                printf("number   : %d\n", data[i].number);
                printf("name     : %s\n", data[i].name);
                printf("colleage : %s\n", data[i].home_dorm.dorm.college);
                printf("dorm_name: %s\n", data[i].home_dorm.dorm.dorm_name);
                putchar('\n');
            }
        }
}

  int input(struct student *data)
  {
        int i = 0;
        do
        {
            printf("Input Non-numeric data to Quit and ");
            printf("Input Number and Name: ");
            if(scanf("%d %s", &data[i].number, data[i].name) != 2) break;
            printf("Input choice( 1:home  or  2:dorm): ");
            scanf("%d",&data[i].type);
            fflush(stdin);
            switch( data[i].type )
            {
                case  1:
                case  2:  home_dorm(&data[i].home_dorm, data[i].type);
                         break;
                default: printf("Input Error!!\n");
                        exit(1);
            }
            i++;
        } while( i < 10);
        return i;
  }

  void home_dorm(union address *pt, int type)
  {
      if(type == 1)
      {
        printf("Input city(wthin 10 characters): ");
        gets(pt->home.city);
        printf("Input address(wthin 20 characters): ");
        gets(pt->home.home_address);
      }
      else
      {
        printf("Input college(wthin 10 charaters): ");
        gets(pt->dorm.college);
        printf("Input dorm name(wthin 10 characters): ");
        gets(pt->dorm.dorm_name);
      }
  }


(1) 비트 필드 (Bit Field)

확인문제 19

/* 비트 필드 형틀 선언, 변수 정의 비트 필드 접근의 예제 */
#include <stdio.h>
void main(void)
{
      struct bit_field
      {
        unsigned  bit1 : 5, bit2: 2;
        unsigned  bit3 : 4, bit4: 3;
      };

      struct bit_field data;
      struct bit_field *pt;

      pt = &data;
      pt->bit1 = 31;
      pt->bit2 = 3;
      pt->bit3 = 15;
      pt->bit4 = 7;
      printf("data.bit1 = %u, data.bit2 = %u\n", pt->bit1, pt->bit2);
      printf("data.bit3 = %u, data.bit4 = %u\n", pt->bit3, pt->bit4);
}

 

확인문제 20

/* 비트 필드의 크기를 확인하는 프로그램 */
#include <stdio.h>
void main(void)
{
      struct bit_field1
      {
        unsigned  bit1 : 5, bit2: 2;
        unsigned  bit3 : 4, bit4: 3;
      }data1;

      struct bit_filed2
      {
          unsigned bit1 : 5; unsigned : 0;
          unsigned bit2 : 3; unsigned : 0;
          unsigned bit3 : 1; unsigned : 0;
          unsigned bit4 : 4;
      } data2;

      struct field3
      {
          unsigned flag1 : 5;
          unsigned flag2 : 8;
          unsigned flag3 : 7;
          unsigned flag4 : 4;
      } data3;

      printf("sizeof(data1) = %d\n", sizeof(data1));
      printf("sizeof(data2) = %d\n", sizeof(data2));
      printf("sizeof(data3) = %d\n", sizeof(data3));
}


(2) typedef문

확인문제 21

/* typedef문을 사용한 새로운 형지정의 정의 예제 */
#include <stdio.h>
int main(void)
{
       typedef int INT, word;

       word a, b, c;
       typedef INT jungsu;
       jungsu i, j, k;

       a = b = c = 3;
       i = j = k = 5;
       printf(" %d %d %d\n", a, b, c);
       printf("%d %d %d\n", i, j, k);
}

 

 

 

그리드형

댓글