📚구조체의 개요

구조체란 서로 다른 자료형을 갖는 자료의 모임을 하나의 자료형으로 정의하여 사용하는 자료형이다. 구조체는 사용자가 정의하여 사용하는 자료형이라 기존의 변수처럼 사용할 수 있다. 구조체는 다양한 형식의 자료를 묶어서 표현할 수 있을 뿐 아니라 사용자가 새로운 형식을 정의하여 사용할 수 있다는 장점이 있다.

1
2
3
4
5
6
struct student
{
    char Name[4];
    int Age;
    int Number;
};



📚구조체의 정의와 선언

📄구조체 정의

1
2
3
4
5
6
struct student
{
    char Name[4];       // 구조체 멤버
    int Age;            // 구조체 멤버
    int Number;         // 구조체 멤버
};

구조체 정의를 통해 student라는 이름의 새로운 자료형이 정의되었다. 이것을 사용자 정의 자료형이라고 하고 구조체를 구성하는 변수들을 구조체 멤버라고 한다.


📄구조체 선언

정의된 구조체를 사용하려면 구조체 변수를 선언해야 한다. 구조체 변수는 일반 변수, 배열, 포인터 등의 형태로 다양하게 선언될 수 있다.

1
struct student a, b;    // 구조체 변수 a, b 선언


구조체는 선언과 동시에 정의도 가능하다.

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
struct student
{
    char Name[4];
    int Age;
    int Number;
} a, b;

// 같은 형의 구조체 변수 사이에 배정 연산자를 사용할 수 있다.
b = a;

// 구조체형과 변수를 동시에 선언할 경우 구조체 이름을 쓰지 않아도 된다.
// 구조체 이름이 없기 때문에 동일 형의 변수는 선언할 수 없다.
struct
{
    char Name[4];
    int Age;
    int Number;
} a1;

// 위와 아래의 구조체 모양은 같지만 컴파일러는 두 형을 다르게 취급하기 때문에 아래와 같은 배정은 불가능하다.

struct
{
    char Name[8];
    int Age;
    int Number;
} b1;

a1 = b1;    // 불가능



📚구조체 초기화

구조체 초기화는 배열 초기화와 같은 방법으로 이루어진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1
struct student
{
    char Name[8];
    int Age;
    int Number;
};

struct student a = {"홍길동", 20, 1};

// 2
struct student
{
    char Name[8];
    int Age;
    int Number;
} a = {"홍길동", 20, 1};



📚구조체 멤버 참조

구조체 변수를 사용하기 위해 구조체 변수 안에 존재하는 구조체 멤버에 접근할 수 있어야 한다. 구조체 멤버에 값을 대입하거나 꺼내려면 멤버 연산자인 도트(.)연산자를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

struct student
{
    char Name[8];
    int Age;
    int Number;
};

void main()
{
    struct student a = { "홍길동", 30, 1 };

    printf("학생 a의 정보: %s, %d, %d \n", a.Name, a.Age, a.Number);
}



📚구조체 배열

동일한 구조를 갖는 구조체 변수가 여러 개 사용될 때 구조체 변수를 대표하는 배열 이름을 설정하여 일반 배열 처럼 사용하는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

void main()
{
    struct student
    {
        char *Name;
        int Age;
        int Number;
    };

    struct student students[3] = { {"홍길동", 30, 1}, {"황진이", 30, 2}, {"임꺽정", 29, 3} };

    for (int i = 0; i < 3; ++i)
    {
        printf("이름: %s 나이: %d 번호: %d \n", students[i].Name, students[i].Age, students[i].Number);
    }
}



📚구조체 포인터

📄구조체 포인터 선언

구조체 포인터는 구조체 변수 선언할 때 *를 변수 앞에 붙여서 포인터로 선언한다. 구조체 포인터는 주소값을 갖게 되며 자료가 있는 곳을 가리킨다.

1
2
3
4
5
6
7
8
9
10
11
struct student
{
    char Name[8];
    int Age;
    int Number;
}

struct student a;
struct student *p;      // 구조체 포인터 p선언

p = &a;                 // 포인터 변수 초기화


📄구조체 포인터 멤버 참조

  • 도트 연산자(.) 사용
    (*p).Name
    *보다 .연산의 우선순위가 높기 때문에 도트 연산자를 사용할 경우 괄호를 사용해야 한다.

  • 포인터 연산자(->) 사용
    p->Name

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
#include <stdio.h>

struct student
{
    char* Name;
    int Age;
    int Number;
};

void main()
{
    struct student students[3] = 
    { 
        {"홍길동", 30, 1}, 
        {"황진이", 30, 2}, 
        {"임꺽정", 29, 3} 
    };
    struct student* p;

    p = students;

    printf("%s %d %d \n", p->Name, p->Age, p->Number);

    p += 2;
    printf("%s %d %d \n", p->Name, p->Age, p->Number);

    --p;
    printf("%s %d %d \n", p->Name, p->Age, p->Number);
}



📚함수와 구조체

📄구조체를 함수의 매개변수로 사용

구조체를 함수의 매개변수로 사용하는 방법은 일반 변수를 함수의 매개변수로 사용하는 것과 같다. 구조체를 값에 의한 자료전달로 매개변수를 사용하면 구조체 내용 전체가 복사되기 때문에 시간이 많이 걸리고 기억공간의 낭비가 심하다는 단점이 있다.

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
#include <stdio.h>

struct num
{
    int X;
    int Y;
    int Sum;
};

struct num Sum(struct num number2)
{
    number2.Sum = number2.X + number2.Y;

    return(number2);
}

void main()
{
    struct num number1;
    number1.X = 1;
    number1.Y = 2;

    number1 = Sum(number1);

    printf("x:%d, y:%d, sum:%d \n", number1.X, number1.Y, number1.Sum);
}


📄구조체 포인터를 함수의 매개변수로 사용

구조체 포인터를 함수 매개변수로 사용하면 구조체를 복사하지 않아도 되기 때문에 프로그램 실행 속도를 향상시킬 수 있고 기억공간의 사용 효율도 올라가는 장점이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

struct num
{
    int X;
    int Y;
    int Sum;
};

struct num Sum(struct num *number2)             // 구조체 포인터 매개변수
{
    number2->Sum = number2->X + number2->Y;     // 포인터 연산자 사용
}

void main()
{
    struct num number1;
    number1.X = 1;
    number1.Y = 2;

    Sum(&number1);                              // 참조 호출

    printf("x:%d, y:%d, sum:%d \n", number1.X, number1.Y, number1.Sum);
}



📚typedef

typedef는 이미 존재하는 자료형에 새로운 이름을 붙일 때 사용하는 키워드이다. 기존 자료형의 이름을 바꾸거나 구조체형을 선언하는데 많이 사용된다.

1
2
3
4
5
typedef unsigned int BYTE;
BYTE val;                   // unsigned int형을 BYTE라는 새로운 이름으로 정의

typedef int* PTR;
PTR p1, p2;                 // PTR p1, p2는 int* p1, p2를 의미


사용 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

struct num
{
    int X;
    int Y;
};

typedef struct num NUMBER;

void main()
{
    NUMBER n = { 0, 1 };

    printf("n.X = %d, n.Y = %d \n", n.X, n.Y);
}


아래와 같이 한번에 사용할 수도 있다.

1
2
3
4
5
typedef struct num
{
    int X;
    int Y;
} NUMBER;



Tags: ,

Categories:

Updated:

Leave a comment