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

구조체 요소가 한꺼번에 뭉쳐져 있는 배열이 아닌 요소마다 메모리를 할당하고 싶을 수도 있습니다. 이때는 구조체 포인터 배열을 만들고 malloc 함수로 각 요소에 메모리를 할당하면 됩니다.

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

  • struct 구조체이름 *포인터이름[크기];

다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

struct_pointer_array.c

#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);    // 10 20
    printf("%d %d\n", p[1]->x, p[1]->y);    // 30 40
    printf("%d %d\n", p[2]->x, p[2]->y);    // 50 60

    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 *)는 구조체 포인터의 크기입니다. 꼭 기억하세요.

구조체 포인터 배열에서 각 요소에 접근하려면 배열 뒤에 [ ] (대괄호)를 사용하며 대괄호 안에 인덱스를 지정해주면 됩니다. 단, 배열 안에 들어있는 요소가 포인터이므로 -> (화살표 연산자)를 사용하여 멤버에 접근해야 합니다. 그래서 p[0]->x와 같은 모양이 되겠죠?

  • 배열[인덱스]->멤버
그림 53‑2 구조체 포인터 배열

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

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

지금까지 구조체 배열과 구조체 포인터 배열에 대해 알아보았는데 문법이 조금 헷갈릴 수 있습니다. 여기서는 배열에 일반 구조체가 들어있으면 점으로 접근하고, 포인터가 들어있으면 화살표로 접근한다는 점만 기억하면 됩니다.