Coding & Programming/C언어 기초(A-Z)

[C언어 기초코딩: 예제로 간단 정리] 10. 구조체(structure)

mainCodes 2021. 3. 17. 19:13

JollyTree의 C언어 기초코딩: 예제로 간단 정리 - 10. 구조체(structure)

 

안녕하세요 JollyTree입니다(•̀ᴗ•́)و 

구조체(structure)는 서로 다른 자료형(char, int, float, double 등) 변수들을 함께 그룹으로 만들수 있는 문법입니다. 구조체를 선언하는 형식은 다음과 같습니다.

    struct 구조체태그명 {
        자료형 변수명; // 멤버 변수
        자료형 변수명; // 멤버 변수
        자료형 변수명; // 멤버 변수
        ...
    };

 

구조체 선언 예:

     struct student_tag {
        int number;      //멤버 변수
        char name[3];    //멤버 변수
        char bloodtype; //멤버 변수
        int age;
    };

 

구조체는 코딩할 때 많이 사용하는 문법으로 구조체 멤버는 일반 변수와 같이 개발자가 목적에 맞게 선언할 수 있습니다. 구조체를 선언한 후에는 구조체 변수를 이용하여 구조체 내의 멤버 변수를 아래와 같이 단일 변수 또는 배열로 선언할 수 있습니다.

구조체 변수 선언 예: 
    student_basic_tag student;       // 구조체 변수 선언

    student_basic_tag student[10];  // 구조체 배열 변수 선언

구조체 내의 변수들은 메모리 공간에 순서대로 나열 되는데 변수를 아래와 같이 선언하고 초기화 했다고 가정하면,

 

    struct student_tag std = {2102, "Ju", 'A', 23};

 

메모리 공간에는 아래 그림과 같이 멤버 변수들이 순서대로 나열되어 총 12바이트의 공간을 차지 하게 됩니다.

 

예제로 구조체에 대해 설명해 보도록 하겠습니다. 예제 코드는 구조체 및 구조체 변수 선언 방법과 함께 아래 내용을 포함하고 있습니다. 예제 코드에도 동일한 번호로 주석을 달아놓았으니 참고하세요.

 

    1. 구조체 멤버 변수 참조
    2. 구조체 포인터 변수
    3. typedef로 정의된 구조체 변수 
    4. 구조체 배열 변수
    5. 공용체(Union)

 

구조체 전체 예제:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
 
struct student_ex_tag {
    int  age;          //나이, 구조체 멤버 변수
    char addr[256];    //주소, 구조체 멤버 변수
};
 
struct student_basic_tag {
    int number;       //번호, 구조체 멤버 변수
    char name[50];    //이름, 구조체 멤버 변수
    char birth[30];   //생년월일, 구조체 멤버 변수
    struct student_ex_tag std_ex;  //구조체 변수
};
 
typedef struct rectangle {
    int x;
    int y;
    int height;
    int width;
} RECT;   //RECT라는 새로운 자료형을 정의
 
int main()
{
    student_basic_tag student;      //구조체 변수 선언
    student_basic_tag* p_student;   //구조체 변수 선언
 
    //새로운 자료형으로 구조체 변수 선언과 초기화
    RECT rect1 = { 10203040 };
 
    //구조체 배열 선언과 초기화
    RECT rect_arrary[3= {
        {10111213},
        {20212223},
        {30313233} };
    int i = 0;
 
    //1.구조체의 멤버 변수 참조
    student.number = 202101;
    strcpy(student.name, "Hong Gil-Dong");
    strcpy(student.birth, "2000.08.20");
    student.std_ex.age = 22;
    strcpy(student.std_ex.addr, "서울 강남구");
 
    printf("number = %d\n", student.number);
    printf("name = %s\n", student.name);
    printf("birth = %s\n", student.birth);
    printf("age = %d\n", student.std_ex.age);
    printf("addr = %s\n", student.std_ex.addr);
 
    //2.구조체 포인터 변수
    p_student = &student; //주소 대입
 
    // 구조체 포인터 변수는 -> 연산자 사용
    printf("\nnumber = %d\n", p_student->number);
    printf("name = %s\n", p_student->name);
    printf("birth = %s\n", p_student->birth);
    printf("age = %d\n", p_student->std_ex.age);
    printf("addr = %s\n", p_student->std_ex.addr);
 
    //3.typedef로 정의된 구조체 변수 
    rect1.x = 100;
    rect1.y = 200;
    rect1.height = 300;
    rect1.width = 400;
 
    //4.구조체 배열 변수
    //입력
    printf("\n\n");
    for (i = 0; i < 3; i++)
    {
        printf("%d번째 사각형의 x 값 입력 : ", i);
        scanf("%d"&rect_arrary[i].x);
 
        printf("%d번째 사각형의 y 값 입력 : ", i);
        scanf("%d"&rect_arrary[i].y);
 
        printf("%d번째 사각형의 height 값 입력 : ", i);
        scanf("%d"&rect_arrary[i].height);
 
        printf("%d번째 사각형의 width 값 입력 : ", i);
        scanf("%d"&rect_arrary[i].width);
    }
 
    //출력
    printf("\n\n>> 입력한 값 출력 \n");
    for (i = 0; i < 3; i++)
    {
        printf("%d번째 사각형의 x      = %d\n", i, rect_arrary[i].x);
        printf("%d번째 사각형의 y      = %d\n", i, rect_arrary[i].y);
        printf("%d번째 사각형의 height = %d\n", i, rect_arrary[i].height);
        printf("%d번째 사각형의 width  = %d\n", i, rect_arrary[i].width);
    }
 
    //5. 공용체(Union)
    {
        union bag {
            char watch;
            int phone;
            char pen[6];
        };
 
        union bag ubag;
 
        ubag.watch = 'A';
        ubag.phone = 200;
        strcpy(ubag.pen, "magic");
 
        printf("\n");
        printf("ubag.watch = %c\n", ubag.watch);
        printf("ubag.phone = %d\n", ubag.phone);
        printf("ubag.watch = %s\n", ubag.pen);
    }
 
    return 0;
}
cs

 

실행결과:

 

1. 구조체의 멤버 변수 참조


예제에서와 같이  student_basic_tag student; 를 선언한 후 각각의 멤버 변수 참조는 '.' 연산자를 통해 가능하며 사용법은 일반 변수와 동일합니다.

2. 구조체 포인터 변수


포인터로 선언된 구조체 변수는 '->' 연산자를 통해 멤버 변수를 참조합니다.

3. typedef 키워드를 이용한 자료형 선언

예제와 같이 typedef를 이용하여 선언된 구조체를 새로운 자료형으로 정의할 수도있습니다. typedef의 사용 형식은
아래와 같습니다.

    typedef struct 구조체태그명 {
        자료형 변수명;
        자료형 변수명;
        자료형 변수명;
        ...
    }새로운_자료형;


변수 선언 예:
    RECT rect1;
    RECT rect2 = { 10, 20, 30, 40 }; 

 

[참고] typedef는 구조체 뿐만 아니라 다양한 형태로 새로운 자료형을 정의할 수도 있습니다.
예)
    typedef unsigned char UCHAR
    typedef unsigned float UFLOAT
    typedef int  INT32;
    typedef unsigned int  UINT32;

    UCHAR ch;
    INT32 num;
    UINT32 avg;

 

4. 구조체 배열 변수


구조체 변수도 일반 변수와 같이 대괄호([, ])를 이용하여 변수를 선언할 수 있으며 선언과 동시에 초기화도 가능합니다. 변수 사용의 기본 개념은 일반 변수와 동일합니다.

    RECT rect_arrary[10];     //배열 변수만 선언


    RECT rect_arrary[3] = {  //배열 변수 선언과 초기화
        {10, 11, 12, 13},        //[0] 번째 원소의 멤버변수 x, y, height, width 순으로 초기화
        {20, 21, 22, 23},        //[1] 번째 원소의 멤버변수 x, y, height, width 순으로 초기화
        {30, 31, 32, 33} };      //[2] 번째 원소의 멤버변수 x, y, height, width 순으로 초기화

5. 공용체(Union)


구조체(struct)와 유사한 것으로 공용체(Union)가 있습니다. 기본적인 사용 방법은 구조체와 유사하며, 구조체는 각각의 멤버 변수가 별도의 메모리 공간을 차지하지만, 공용체는 같은 메모리를 멤버 변수들이 공유합니다. 멤버변수 중 크기가 큰 변수의 메모리가 할당되어 멤버들 간에 공유하게 됩니다. 공용체 선언 형식은 다음과 같습니다.

    union 공용체태그명(이름)
    {
        자료형 변수명;
        자료형 변수명;
        ...
    };

 

공용체 선언 예:
    union bag{
        char watch;
        int phone;
        char pen[6];
    };

메모리 상의 구조는 구조체와 같이 각각의 멤버변수가 메모리 공간을 각각 차지하지 않고 배열을 포함하여 멤버 변수 중 가장 큰 멤버 변수가 바로 공용체의 메모리 크기가 됩니다. char pen[6]; 멤버 변수가 총 6바이트로 가장 크기 때문에 6바이트의 메모리 공간을 차지하며 watch, phone 변수도 6바이트 내에서 메모리 공간을 함께 사용하게 됩니다. 

 

※ watch 1바이트의 메모리 공간 사용, phone 1~4까지의 메모리 공간 사용, pen[6]은 1~6까지의 메모리 공간 사용 

 

공용체가 멤버 변수들 간에 메모리를 공유하기 때문에 메모리를 절약할 수 있지만, 메모리를 공유하기 때문에 동시에 멤버변수를 사용하다 보면 코드가 복잡해지기도 하고 실행결과에서 보는 것과 같이 알 수 없는 오류가 발생할 가능성이 높은 것으로 알려져 있습니다.

 

예제에서는 pen 멤버변수는 입력한 "magic"이 정상적으로 출력되었지만 watch와 phone 멤버 변수는 입력한 값과 다른 값이 출력되었습니다. 메모리가 정말 부족한 환경에서는 공용체를 사용할 수 있으나 요즘은 메모리가 충분하기 때문에 공용체를 잘 사용하지 않습니다.

 

이상 JollyTree였습니다 (•̀ᴗ•́)و