기타 동적 할당 함수(calloc, realloc)
calloc, realloc
malloc 외에도 heap영역에 접근하게 해주는 함수가 더 있습니다.
calloc과 realloc 입니다.
어원 부터 살펴 보겠습니다.
calloc 은 clear와 allocation의 줄임 표현입니다.
clear = 청소하다
allocation = 할당
할당된 heap 영역을 청소하라는 의미입니다.
realloc의 어원입니다.
reallocation 이라는 단어가 따로 존재하는데 re+allocation 라고 봐야 되겠죠
다시 할당하다 라는 말입니다.
calloc은 메모리를 0으로 초기화 하는 역할을 하고
realloc은 메모리를 늘리거나 줄이는 역할을 합니다.
어원을 알아야 하는 이유가 여기 더 있습니다.
어원을 모르면 그냥 늘리거나 줄이는 거라고 알게 되겠지만
어원을 알고 있다면 별도로 암기 하지 않아도 realloc이 메모리를 다시 할당하는 것이라고 알 수 있습니다.
메모리 구조를 보면 힙 영역도 위에서 아래로 메모리가 사용되는데 메모리 할당 영역을 늘리는 과정에서 아래에 다른 할당된 영역이 있을 경우 전체적인 자리 변환이 필요하게 됩니다.
이런 경우에는 기존에 할당했던 메모리를 자동으로 free 해준 뒤에 다른 공간에 메모리를 할당하게 됩니다. 주소값이 바뀌는 거죠.
예제를 통해 학습해보기
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int* pi;
int size = 5;
int count = 0;
int num;
int i;
pi = (int*)calloc(size, sizeof(int)); //using calloc, get 5 * 4byte of memory
while (1) //infinity loop
{
printf("양수만 입력하세요 => ");
scanf("%d", &num); //get input
if (num <= 0) break; //untill input under than 0
if (count == size) //
{
size += 5;
pi = (int*)realloc(pi, size * sizeof(int)); //get memory again to pi.
}
pi[count++] = num; //save value to next memory, and add+1 to count
}
for (i = 0; i < count; i++) //Printing all array indexes that have a value
{
printf("%5d", pi[i]);
}
free(pi);
return 0;
}
11번행을 보면 calloc의 원형(proto type)을 알 수 있습니다.
pi = (int*)calloc(size, sizeof(int));
라고 되어있는데
원형은 이렇습니다.
void* calloc(unsigned int, unsigned int);
매개변수로 정수형태 2개를 받는것으로 보입니다.
calloc은 특이하게도 메모리를 할당 할 때에 배열형태로 할당합니다.
첫번째 정수형 매개변수는 배열의 size를 의미하고, 두번째 정수형 매개변수는 배열 index 1개당 메모리 크기를 의미합니다.
즉, 11번행은 pi라는 포인터에 주소값을 할당하는데 그것은 4바이트(정수형의 메모리 크기)의 저장공간을 5개만큼 배열형태로 할당한 다음 그 시작점의 주소값을 할당한다는 이야기죠.
다음은 20번행을 볼까요?
pi = (int*)realloc(pi, size * sizeof(int));
라고 되어있습니다.
realloc의 원형은 이렇습니다.
void* realloc(void* , unsigned int);
매개변수 역시나 2개인데 첫번째 매개변수는 포인터 형태입니다. 주소값 형태로 된 녀석을 하나 받고
다음으로 정수형태를 하나 받네요
여기서 첫번째 매개변수인 주소값은 다시 할당하고 싶은 메모리 주소값이예요.
이 값을 NULL로 설정하면 malloc과 동일한 기능을 수행할 수 있습니다. '재' 할당인데, '재' 를 없애버린거나 다름 없죠.
어쨌거나 첫번째 매개변수는 heap영역의 메모리 주소가 되면 됩니다.
두번째 매개변수는 누구나 예상할 수 있듯이, 다시 할당하고 싶은 주소의 크기입니다. 그 주소의 할당 영역을 줄이거나 늘리거나 할 수 있는거라고 보면 되지요.
그러면 20번행은 어떤 의미일까요?
우항을 좌항으로 대입하는 것이니까 우측부터 읽으면 얼추 맞습니다.
pi라는 heap 메모리 주소에 size * sizeof(int) 만큼의 저장공간을 다시 할당해 준다음 그 시작부분의 첫번째 메모리 주소값을 pi에 대입하겠다는 이야기입니다.
여기서 size의 값이 처음에 5였다가 while문의 반복되면서 count값이 5가 되고 5가 된 이후에도 추가로 루프될 때에 10으로 늘어나기 때문에 (10 * 4), (15 * 4), (20 * 4) ... 이렇게 늘어나는 형태가 되겠네요
지금까지 배운 3가지 동적할당 함수 (malloc, calloc, realloc) 모두는 할당할 heap영역에 공간을 찾지 못하면 주소값으로 NULL값을 반환하게 됩니다. 따라서 호출 후에는 항상 null 검사를 통해 메모리값이 제대로 할당되었는지 검사하는 과정이 있어야 하겠습니다.