C언어는 정적(static) 메모리만 사용하는 언어가 아니다.
실행 중에 필요한 만큼 메모리를 직접 요청하고 해제할 수 있는 기능, 즉 동적 메모리 할당
도 지원한다.
이를 통해 배열의 크기를 런타임에 정하거나, 메모리를 효율적으로 활용할 수 있게 된다.
보통 배열은 선언할 때 크기를 고정해야 한다.
int arr[10]; // 크기 10 고정
하지만 입력받은 값에 따라 배열 크기가 달라질 수 있다면..?
이럴 땐 미리 크기를 정할 수 없기 때문에 동적으로 메모리를 할당해야 한다.
동적할당이 꼭 정답은 아니다. 경우에 따라서 입력받을 사이즈를 제한하면서 시스템을 운영하는 것이, 오히려 안정적이고 적절할 수 있다.
가장 기본적인 메모리 할당 함수는 malloc()
이다.
int *arr = (int *)malloc(sizeof(int) * 5);
if (arr == NULL) {
printf("메모리 할당 실패\n");
}
malloc()은 할당에 실패하면 NULL을 반환하므로 꼭 체크해야 한다.
int *arr = (int *)calloc(5, sizeof(int));
calloc()
은 malloc()과 달리 0으로 초기화된 메모리를 할당해준다.속도 때문인지, 현업에서는 calloc보다는 malloc위주로 사용한다. 아무래도 초기화를 하면, 그만큼 처리하는 시간은 늘어난다.
arr = (int *)realloc(arr, sizeof(int) * 10);
realloc()
은 이미 할당된 메모리 크기를 늘리거나 줄일 때 사용동적으로 할당한 메모리는 반드시 사용 후 해제해줘야 한다.
free(arr);
free()
를 하지 않으면 프로그램이 종료돼도 메모리가 남아 있게 되고, 메모리 누수(leak)
발생 가능free(arr);
arr = NULL;
int n;
printf("몇 개의 정수를 입력할까요? ");
scanf("%d", &n);
int *nums = (int *)malloc(sizeof(int) * n);
if (nums == NULL) {
printf("메모리 할당 실패\n");
return 1;
}
// 값 입력
for (int i = 0; i < n; i++) {
printf("%d번째 정수 입력: ", i + 1);
scanf("%d", &nums[i]);
}
// 출력
printf("입력된 값들: ");
for (int i = 0; i < n; i++) {
printf("%d ", nums[i]);
}
free(nums);
이 예제는 사용자 입력을 기반으로 동적 배열을 만들고 처리한 뒤, 마지막에 free()로 메모리를 해제한다.
실무에서 굉장히 흔하게 쓰이는 패턴이다.
함수 | 역할 |
---|---|
"malloc" | 초기화되지 않은 메모리 할당 |
"calloc" | 0으로 초기화된 메모리 할당 |
"realloc" | 이미 할당한 메모리의 크기 조절 |
"free" | 할당된 메모리 해제 |
동적 메모리는 포인터와 함께 쓰이기 때문에 처음엔 어렵게 느껴질 수 있지만,
한 번 개념이 잡히면 메모리 효율과 유연한 프로그램 구조를 만들 수 있는 아주 강력한 도구가 된다.
@nullvuild