본문 바로가기

C

([C언어] 23강) 메모리의 동적할당 (malloc, calloc, realloc, free)

안녕하세요 잭클입니다.

 

이번시간에는 메모리의 동적할당에 대해 배워볼까 하는데요!

 

우선 우리가 배열은 포인터다 라는 개념을 알고있으니

 

int arr[4];
int * ptrArr = arr;

이 코드의 의미를 알고있을겁니다.

 

자 그럼 아래 코드를 한번 보시죠

 

int arr;
int * ptrArr = &arr;

자 위 코드를 보시면 1번코드 2번코드의 ptrArr은

 

모두 int 포인터형 변수라는것을 알 수 있습니다

 

하지만 두코드 모두에 ptrArr[1];을 해주면

 

두번째코드에서만 오류를 발견하게됩니다.

 

어차피 포인터는 자신이 포인터인것만 기억할뿐,

 

배열이라는것은 모를텐데 왜 둘의 결과가 다른걸까요?

 

이유는 이렇습니다. 1번코드에서는 4개 배열인 arr이 생성되면서

 

메모리에서 4개의 공간을 내주게 됩니다.

 

4개의 공간은 사용할수있는 공간이다! 라고 써주는거라고 보시면 될것같네요.

 

그래서 ptrArr[1]을 해주면 주소를 검사하고 "사용할수 있는 공간이네" 라고 판정되어

 

사용해도 에러가 나지 않습니다.

 

하지만 2번 코드의 arr은 배열이 아닌 그냥 int형입니다 즉, 단 한개의 공간만 사용하겠다!

 

라고 해준것이고요 ptrArr[1]을 해주면 어라? 이 공간은 사용하겠다고 한적없는데?

 

에러!

 

이렇게 되는겁니다.

 

오늘 배워볼 동적할당에 대해 설명하자면 메모리를 동적으로 사용하겠다고 해주고

 

그 공간을 사용하는것이라고 보면 됩니다.

 

자 그럼 하나씩 배워볼까요?

 

우선 malloc! (공식 발음은 무엇인지 모르겠으나 저의경우 엠얼록 이라고 발음합니다)

-멜록이라고 부르는 사람들도 있더라구요-

 

malloc의 기능은 사용하지 않고있는 메모리 공간을 동적으로 사용하겠다고 명시해주고

 

그 공간을 반환하는 역할을 합니다! 사용법을 한번 볼게요!

 

우선 동적할당 관련 코드들은 stdlib헤더에 정의되어 있습니다

 

stdlib헤더를 include해주세요!

 

malloc(size)

이렇게 사용하면 됩니다!

 

size에는 동적으로 사용할 메모리의 크기를 넣으면 됩니다.

 

예를들어 int 형 4개요소 배열처럼 사용할것이다

 

그럼 sizeof(int) * 4 이렇게 해주면 되겠죠?

 

자 그럼 여기서 동적할당의 이점을 하나 말씀드릴게요

 

int len = 4;
int arr[len];

이렇게하면 어떤현상이 발생할까요?

 

에러가 납니다. 배열의 길이 선언에는 고정된 수가 들어가야합니다

 

변수가 들어갈수 없습니다.

 

그럼 malloc에서는 어떨까요?

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int len = 4;
    int * arr = (int*)malloc(sizeof(int) * len);
}

이렇게 하면 원하는대로 len의 값만큼 동적할당되겠네요!

 

근데 여기서 잠깐! malloc앞에 (int *) 이건 뭘까요? 이건 다음시간에 배울테니

 

int *형 주소를 얻고싶은거면 (int *) 이런식으로 자료형을 적어주세요!

 

다음 시간에 상세히 알려드리도록 하겠습니다!

 

 

 

자 이제 동적할당을 했네요! 그럼 사용을 해봐야겠죠?

 

사용은 일반적인 포인터와 100% 똑같습니다!

 

정말인지 한번 확인해볼까요?

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int len = 4;
    int * arr = (int *)malloc(sizeof(int) * len);
    for(int i = 0; i < len; i++)
    {
        *(arr + i) = i;
    }
    for(int i = 0; i < len; i++)
    {
        printf("%d",arr[i]);
    }
}

 

자 이 코드라면 포인터의 효과를 확실히 볼 수 있겠네요!

 

실행해보죠!

 

자 원하는 답이 나오는군요!

 

 

그럼 이번엔 calloc에 대해서 알아볼까요?

 

calloc도 공식 발음은 잘 모르지만 저같은경우엔 씨얼록이라고 부릅니다!

-콜록이라고 부르는 경우도 본적 있습니다-

 

calloc은 malloc과 같은일을 하지만 malloc과 달리

 

모든 요소를 0으로 초기화해서 반환해줍니다!

 

calloc의 사용법은 아래와 같습니다

 

calloc(count, size);

엥 똑같다면서 왜 calloc은 매개변수가 2개죠?

 

calloc의 사이즈에는 갯수까지 계산된 사이즈가 아니라,

 

자료형의 사이즈를 넘겨주고 count에는 요소의 갯수를 넘겨주면 됩니다

 

malloc에서 int형 4칸 배열을 만들기위해 4 * 4 해서 16을 넘겨줬다면

 

calloc은 (4,4)를 넘겨주면 되는겁니다.

 

자 그럼 한번 해볼까요?

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int len = 4;
	int* arr = (int*)calloc(len,sizeof(int));
	for (int i = 0; i < len; i++)
	{
		printf("%d",arr[i]);
	}
}

이렇게 하면 calloc을 통해 int형 4칸 배열 포인터가 만들어지고

 

전부 0으로 초기화 된다고 했으니 0000이라고 출력되어야 정상이겠네요!

 

실행해보죠!

 

 

성공입니다!

 

이해 하셨나요?

 

그럼 realloc에 대해서 배워보도록 하겠습니다

 

realloc의 발음은 저같은경우엔 리얼록이라고 부릅니다!

 

realloc의 기능은 말그대로 re! 다시! 동적할당했던 메모리의 길이를

 

재조정하는 함수입니다!

 

realloc의 사용법은 아래와 같습니다!

 

realloc(pointer, size);

이렇게 사용하시면 되는데요!

 

기존에 4라고 동적할당 해놓았던 포인터를

 

realloc의 매개변수로 넘겨주고 size를 정해주면

 

size만큼 길이를 변경시켜 다시 반환해줍니다!

 

한번 해보아야겠죠?

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int len = 4;
    int len2 = 10;
    int* arr = (int*)malloc(sizeof(int) * len);
    for (int i = 0; i < len; i++)
    {
        arr[i] = i;
    }
    realloc(arr, sizeof(int) * len2);
    for (int i = len; i < len2; i++)
    {
        arr[i] = i;
    }
    for (int i = 0; i < len2; i++)
    {
        printf("%d", arr[i]);
    }
}

이 코드의 결과는!?

 

0123456789라고 떠야 정상이겠네요

 

처음에는 4만큼 동적할당하고 0123을 할당해주지만

 

realloc으로 10칸으로 재조정하고 456789를 다시 넣었으니

 

한번 결과를 볼까요?

 

성공입니다!!

 

 

자 그럼 마지막이네요

 

동적할당은 우리가 쓰는 일반적인 메모리와 다른공간에있는

 

힙메모리 라는 공간에서 메모리를 얻어와서 쓰게됩니다.

 

우리는 이 메모리를 더이상 쓰지않을때 수동으로 해제시켜줘야하는데요

 

파일 입출력을 배웠을때 fopen을 했다면 fclose를 했던것 기억 나시나요?

 

그처럼 malloc또는 calloc으로 동적할당을 받았다면

 

무조건 메모리 해제! free를 사용해 메모리를 풀어주어야합니다.

 

free의 사용법은

 

free(pointer);

입니다!

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int len = 4;
    int len2 = 10;
    int* arr = (int*)malloc(sizeof(int) * len);
    for (int i = 0; i < len; i++)
    {
        arr[i] = i;
    }
    realloc(arr, sizeof(int) * len2);
    for (int i = len; i < len2; i++)
    {
        arr[i] = i;
    }
    for (int i = 0; i < len2; i++)
    {
        printf("%d", arr[i]);
    }
    free(arr);
}

 

이렇게 하면 되겠네요!

 

자 오늘 강좌는 여기까지입니다! 동적할당은 여러모로 편하고

 

나중에도 많이 쓰게 될 개념이니 꼭 외워 두시길 바랄게요!

 

수고하셨습니다!

 

다음강좌! (자동적 형변환, 명시적 형변환)에서 봬요~