OneDev
[C] 23. 메모리 동적 할당(Dynamic Memory Allocation) - malloc, free 본문
◎ 동적 할당(Dynamic Memory Allocation)
- "동적 할당" 이란 → 프로그램이 실행단계에서(프로그램 실행중에) 사용할 메모리 공간을 직접 할당하는 것
- 컴파일 단계에서 메모리를 할당하는 정적(static) 할당과 비교된다
- 상황에 따라 원하는 만큼 메모리를 할당할 수 있고, 이미 할당된 메모리라 해도 크기를 조절할 수 있다
- malloc 함수를 이용해 메모리를 할당하고, free 함수를 이용해 할당을 해제해줘야 한다
◎ malloc, free 함수
- <stdlib.h> 에 정의되어 있다 ( <stdlib.h> 를 include 해줘야 한다)
- malloc 함수의 리턴형 : (void *) 형
- malloc 함수를 이용해 메모리를 할당받은 메모리는 이후에 free 함수를 이용해 해제해주어야 한다 ( 해제하지 않을 시 메모리 누수 memory leak 이 발생)
- 힙(Heap) 영역에 메모리를 할당
- 상당히 느린 함수들 중 하나이다
◎ malloc 을 이용해 가변길이 배열 만들기
- 배열의 크기를 정확히 모르거나 사용자의 입력에 따라 배열의 크기를 정의하고 싶을 때 사용
- malloc 의 리턴 타입은 (void *) 형이기 때문에 원하는 형으로 형변환 해주면 된다
- 메모리를 할당할 때 보통 [ sizeof(데이터타입) * 배열의 크기 ] 와 같이 할당한다
/* 예시 - 학생들의 총점 구하기 */
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv) {
int student; // 입력받고자 하는 학생 수
int i, input;
int *score; // 학생들의 점수
int sum = 0; // 총점
printf("학생들의 수는? : "); // 배열의 크기 -> 사용자 입력
scanf("%d", &student);
score = (int *)malloc(student * sizeof(int)); // malloc 을 이용한 동적할당
for (i = 0; i < student; i++) {
printf("학생 %d 의 점수 : ", i);
scanf("%d", &input);
score[i] = input;
sum += score[i];
}
printf("총점 : %d \n", sum);
free(score); //할당받은 메모리 해제
return 0;
}
◎ 2차원 배열의 동적 할당
2차원 배열 또한 동적으로 할당할 수 있는데, 크게 두 가지 방법을 생각해 볼 수 있다
- 포인터 배열을 사용해 2차원 배열 처럼 동작하는 배열을 만드는 방법
- 실제로 2차원 배열 크기의 메모리를 할당한 뒤 2차원 배열 포인터로 참조하는 방법
(1) 포인터 배열을 이용해서 2차원 배열 할당하기
- 포인터 배열 - 배열의 각 원소들이 모두 포인터인 배열
- 먼저 포인터 배열을 동적으로 할당한 뒤, 각각의 원소들이 가리키는 일차원 배열을 다시 동적으로 할당
- 이 방법으로는 진짜 2차원 배열처럼 메모리에 연속적으로 존재하는 배열을 만들 수는 없다
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv) {
int x, y;
int** arr; // 이차원 배열 arr[x][y] 만들기
scanf("%d %d", &x, &y);
// 1. (int *) 형 원소를 x 개 가지는 1차원 배열 생성
arr = (int**)malloc(sizeof(int) * x);
// 2. x 개의 원소가 가리키는 1차원 배열들 각각 할당
for (int i = 0; i < x; i++) {
arr[i] = (int*)malloc(sizeof(int) * y);
}
// 해제는 역순
for (int i = 0; i < x; i++) {
free(arr[i]);
}
free(arr);
return 0;
}
(2) 실제 2차원 배열 할당하기
- 이 방법은 C99 이상의 버전 (VLA 를 지원하는 버전) 에서만 사용 가능하다.
- 메모리에 연속적으로 존재하는 진짜 2차원 배열을 만들기 위해서는 반드시 malloc 을 통해 해당 공간을 할당해야 한다
- 2차원 배열 포인터의 경우 포인터 연산을 수행하기 위해 반드시 포인터 타입 안에 행 길이가 들어가야 한다
- 이를 고려하여 아래와 같이 2차원 배열 포인터를 정의할 수 있다
// arr[x][y];
int (*arr)[y] = (int (*)[y])malloc(x * y * sizeof(int));
- (주의) 정의 할 때 반드시 행의 길이(y) 에 값이 들어간 후에 정의해야 한다
- 이렇게 정의했을 경우 모든 데이터가 메모리에 연속적으로 있기 때문에 free 역시 arr에 대해 단 한 번만 수행하면 된다.
(예시)
int main() {
int width, height;
printf("배열 행 크기 : ");
scanf("%d", &width);
printf("배열 열 크기 : ");
scanf("%d", &height);
// Visual Studio 에서는 동작하지 않을 수도 있다
int(*arr)[width] = (int(*)[width])malloc(height * width * sizeof(int));
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int data;
scanf("%d", &data);
arr[i][j] = data;
}
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
free(arr);
}
'Language > C' 카테고리의 다른 글
[C] 24. 매크로 함수 & 인라인(inline) 함수 (0) | 2023.08.10 |
---|---|
[C] memcpy (0) | 2023.08.01 |
[C] 22. 전처리기 (preprocessor) (#include, #define, #error, #ifdef) (0) | 2023.07.26 |
[C] 21. 구조체(struct) (0) | 2023.07.21 |
[C] 20.문자열(String) (0) | 2023.07.18 |
Comments