46. 구조체 배열
1. 키워드
- 구조체 배열
2. 구조체 배열 사용하기
- 2차원 좌표를
10
개 만들려면 간단하게 구조체 변수p1
부터p10
까지 선언하는 방법이 있다.
struct Point2D
{
int x;
int y;
};
// 구조체 변수 10개 선언
struct Point2D p1;
struct Point2D p2;
...
struct Point2D p10;
- 이때는 위의 코드처럼 하는 것보다 구조체를 배열로 만들면 편한다.
3. 구조체 배열 선언하기
- 구조체 배열은 변수 이름 뒤에
[]
(대괄호)를 붙인 뒤 크기를 설정한다.
#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
에 접근한다는 뜻이다.
구조체 배열을 선언하는 동시에 초기화하기
- 구조체 배열을 선언하면서 초기화하려면
{}
(중괄호) 안에{}
를 사용한다.
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,}
을 할당하면 된다.
4. 구조체 포인터 배열 선언하기
- 구조체 요소가 한꺼번에 뭉쳐져 있는 배열이 아닌 요소마다 메모리를 할당하고 싶을 수도 있다.
- 이때는 구조체 포인터 배열을 만들고
malloc
함수로 각 요소에 메모리를 할당하면 된다. - 구조체 포인터 배열은 포인터 변수 이름 뒤에
[]
를 붙인 뒤 크기를 설정한다.
#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 *)
는 구조체 포인터의 크기이다.
- 구조체 포인터 배열에서 각 요소에 접근하려면 배열 뒤에
[]
를 사용하며[]
안에 인덱스를 지정해 주면 된다. - 단, 배열 안에 들어있는 요소가 포인터이므로
->
(화살표 연산자)를 사용하여 멤버에 접근해야 한다.
- 구조체 포인터 배열의 사용이 끝났다면 메모리를 해제해야 한다.
- 다음과 같이 배열 크기만큼 반복하면서 각 요소에 할당된 동적 메모리를 해제한다.
for (int i = 0; i < sizeof(p) / sizeof(struct Point2D *); i++) // 요소 개수만큼 반복
{
free(p[i]); // 각 요소의 동적 메모리 해제
}