Skip to content

46. 구조체 배열


1. 키워드

  • 구조체 배열


2. 구조체 배열 사용하기

  • 2차원 좌표를 10개 만들려면 간단하게 구조체 변수 p1부터 p10까지 선언하는 방법이 있다.


struct Point2D
{
    int x;
    int y;
};

// 구조체 변수 10개 선언
struct Point2D p1;
struct Point2D p2;
...
struct Point2D p10;


  • 이때는 위의 코드처럼 하는 것보다 구조체를 배열로 만들면 편한다.


struct Point2D p[3000]; // 요소가 3,000개인 구조체 배열 선언


3. 구조체 배열 선언하기

  • 구조체 배열은 변수 이름 뒤에 [](대괄호)를 붙인 뒤 크기를 설정한다.


struct 구조체이름 변수이름[크기];
#include <stdio.h>

struct Point2D
{
    int x;
    int y;
};

int main()
{
    struct Point2D p[3]; // 크기가 3인 구조체 배열 생성

    p[0].x = 10; // 인덱스로 요소에 접근한 뒤 점으로 멤버에 접근
    p[0].y = 20;
    p[1].x = 30;
    p[1].y = 40;
    p[2].x = 50;
    p[2].y = 60;

    printf("%d %d\n", p[0].x, p[0].y);
    printf("%d %d\n", p[1].x, p[1].y);
    printf("%d %d\n", p[2].x, p[2].y);

    return 0;
}

// 10 20
// 30 40
// 50 60


  • struct Point2D p[3];과 같이 struct 키워드와 구조체 이름으로 구조체 변수를 선언하면서 [] 안에 넣어주면 배열로 선언할 수 있다.
  • 구조체 배열에서 각 요소에 접근하려면 배열 뒤에 []를 사용하며 [] 안에 인덱스를 지정해 주면 된다.
  • 이 상태에서 다시 멤버에 접근하려면 .(점)을 사용한다.
  • 즉, p[0].x는 구조체 배열의 첫 번째 요소에서 멤버 x에 접근한다는 뜻이다.


배열[인덱스].멤버


001


구조체 배열을 선언하는 동시에 초기화하기

  • 구조체 배열을 선언하면서 초기화하려면 {}(중괄호) 안에 {}를 사용한다.


struct 구조체이름 변수이름[크기] = {{.멤버이름1 = 값1, .멤버이름2 = 값2},
                              {.멤버이름1 = 값3, .멤버이름2 = 값4}};
struct 구조체이름 변수이름[크기] = {{값1, 값2}, {값3, 값4}};


  • 다음과 같이 구조체 배열의 각 요소를 {}로 묶은 뒤 ,(콤마)로 구분해 주면 된다.


#include <stdio.h>

struct Point2D
{
    int x;
    int y;
};

int main()
{
    // 구조체 배열을 선언하면서 초기화
    struct Point2D p1[3] = {
        {.x = 10, .y = 20},
        {.x = 30, .y = 40},
        {.x = 50, .y = 60}};

    printf("%d %d\n", p1[0].x, p1[0].y);
    printf("%d %d\n", p1[1].x, p1[1].y);
    printf("%d %d\n", p1[2].x, p1[2].y);

    // 구조체 배열을 선언하면서 초기화
    struct Point2D p2[3] = {{10, 20}, {30, 40}, {50, 60}};

    printf("%d %d\n", p2[0].x, p2[0].y);
    printf("%d %d\n", p2[1].x, p2[1].y);
    printf("%d %d\n", p2[2].x, p2[2].y);

    return 0;
}

// 10 20
// 30 40
// 50 60
// 10 20
// 30 40
// 50 60


  • 만약 모든 요소의 멤버를 0으로 초기화하고 싶다면 구조체 배열을 선언하면서 {0,}을 할당하면 된다.


struct Point2D p[3] = {0,}; // 구조체 배열을 선언하면서 0으로 초기화


4. 구조체 포인터 배열 선언하기

  • 구조체 요소가 한꺼번에 뭉쳐져 있는 배열이 아닌 요소마다 메모리를 할당하고 싶을 수도 있다.
  • 이때는 구조체 포인터 배열을 만들고 malloc 함수로 각 요소에 메모리를 할당하면 된다.
  • 구조체 포인터 배열은 포인터 변수 이름 뒤에 []를 붙인 뒤 크기를 설정한다.


struct 구조체이름 *포인터이름[크기];
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

struct Point2D
{
    int x;
    int y;
};

int main()
{
    struct Point2D *p[3]; // 크기가 3인 구조체 포인터 배열 선언

    // 구조체 포인터 배열 전체 크기에서 요소(구조체 포인터)의 크기로 나눠서 요소 개수를 구함
    for (int i = 0; i < sizeof(p) / sizeof(struct Point2D *); i++) // 요소 개수만큼 반복
    {
        p[i] = malloc(sizeof(struct Point2D)); // 각 요소에 구조체 크기만큼 메모리 할당
    }

    p[0]->x = 10; // 인덱스로 요소에 접근한 뒤 화살표 연산자로 멤버에 접근
    p[0]->y = 20;
    p[1]->x = 30;
    p[1]->y = 40;
    p[2]->x = 50;
    p[2]->y = 60;

    printf("%d %d\n", p[0]->x, p[0]->y);
    printf("%d %d\n", p[1]->x, p[1]->y);
    printf("%d %d\n", p[2]->x, p[2]->y);

    for (int i = 0; i < sizeof(p) / sizeof(struct Point2D *); i++) // 요소 개수만큼 반복
    {
        free(p[i]); // 각 요소의 동적 메모리 해제
    }

    return 0;
}

// 10 20
// 30 40
// 50 60


  • struct Point2D *p[3];과 같이 구조체 포인터를 선언하면서 [] 안에 크기를 넣어주면 배열로 선언할 수 있다.


  • 하지만 구조체 포인터 배열만 선언하고 메모리를 할당하지 않았으므로 사용할 수는 없다.
  • 그러므로 다음과 같이 배열 크기(요소 개수)만큼 반복하면서 각 요소에 구조체 크기만큼 메모리를 할당해 준다.
  • 이때 구조체 포인터 배열에는 포인터가 들어있으므로 요소 개수를 구하려면 구조체 포인터 배열의 전체 크기에서 구조체 포인터의 크기로 나눠주면 된다.


// 구조체 포인터 배열 전체 크기에서 요소(구조체 포인터)의 크기로 나눠서 요소 개수를 구함
for (int i = 0; i < sizeof(p) / sizeof(struct Point2D *); i++) // 요소 개수만큼 반복
{
    p[i] = malloc(sizeof(struct Point2D)); // 각 요소에 구조체 크기만큼 메모리 할당
}


  • sizeof(struct Point2D)는 구조체가 차지하는 크기, sizeof(struct Point2D *)는 구조체 포인터의 크기이다.


  • 구조체 포인터 배열에서 각 요소에 접근하려면 배열 뒤에 []를 사용하며 [] 안에 인덱스를 지정해 주면 된다.
  • 단, 배열 안에 들어있는 요소가 포인터이므로 ->(화살표 연산자)를 사용하여 멤버에 접근해야 한다.


배열[인덱스]->멤버


002


  • 구조체 포인터 배열의 사용이 끝났다면 메모리를 해제해야 한다.
  • 다음과 같이 배열 크기만큼 반복하면서 각 요소에 할당된 동적 메모리를 해제한다.


for (int i = 0; i < sizeof(p) / sizeof(struct Point2D *); i++) // 요소 개수만큼 반복
{
    free(p[i]); // 각 요소의 동적 메모리 해제
}

References