💡 자료구조

동적할당 malloc 함수

ji-hyun 2021. 6. 16. 18:35
int *p;
p = (int *)malloc(40);
if ( p == NULL) {
	/* 동적 메모리 할당이 실패 */
    /* 적절한 조치를 취한다. */
}

p[0] = 12;
p[1] = 24;
*(p+2) = 36;

malloc이 반환하는 주소는 원래 타입이 없는 주소(void *)이다. 정수들을 저장하기 위해서 이것을 int *로 변환한다.

(반드시 필요한 건 아니다.)

 

 

할당 받을 메모리의 크기를 byte단위로 지정한다. 여기서는 10개의 정수를 저장하기 위해서 40바이트를 요청하였다.

 

malloc으로 할당받은 메모리는 이렇게 보통의 배열처럼 사용한다.

 

첫번째 주소를 리턴해준다. 만약 주소를 잊어버리면 찾기 힘들기 때문에 malloc이 리턴해주는 주소를 보관할 저장소가 필요하다. 그래서 어떤 변수에 저장해서 보관해야 하는데 이때 "메모리 주소를 저장해둘 수 있는 변수 - 포인터 변수" 를 선언해줘야 한다.

 

일반적으로 malloc 함수로 처리할 때 /* ..... */ 와 같이 예외 처리해주는 것이 좋다. 

 

 

 

 


C언어에서는 일반적으로 배열의 크기를 지정해서 사용해야 한다. 하지만 동적 메모리 할당을 통해서 배열의 크기를 더 키울 수 있다. 하지만 엄밀히 말하자면 원래 자체의 배열의 크기를 키운다는 것은 아니다.

 

<배열 키우기>

동적으로 할당된 배열은 공간이 부족할 경우 더 큰 배열을 할당하여 사용할 수 있다.

 

#include <stdio.h>
#include <stdlib.h>   //malloc 함수를 사용하기 위해선 stdlib 라이브러리를 사용해야함

int *array = (int *)malloc( 4 * sizeof(int) );  //16byte
array[0] = 1;
array[1] = 2;
*(array+2) = 3;

/* 배열 array의 크기가 부족한 상황이 발생한다. */

int *tmp = (int *)malloc( 8 * sizeof(int) );
int i;
for (i=0; i<4; i++)
	tmp[i] = array[i];
    
array = tmp;

array[4] = 4;
array[5] = 5;

printf("%d", array[5]);

}

원래 array는 16byte짜리 공간을 가지고 있었지만 공간의 크기가 부족한 상황이 발생한다면 다음과 같이 해줄 수 있다.

tmp에 array의 2배인 32byte 공간을 선언하고 메모리를 동적으로 할당해준다.

for문을 통해서 array의 원소들을 tmp에 옮겨주고 

마지막 코드에서 tmp의 시작주소를 array에 치환시켜준다.

 

 

쉽게 이해하기 위해 그림과 같이 보면, array의 까만 화살표가 없어지게 된다는 뜻이다.

그리고 array는 빨간 화살표로 시작 주소를 가진다고 생각하면 이해가 쉽겠다. (tmp의 시작 주소를 치환시켜줬기 때문)

 

그럼 원래의 16바이트짜리의 공간은 어떻게 될까? 4칸짜리의 주소를 가진 애는 없게 된다. 이런 애를 보통 가비지라고 한다. 그냥 쓰지 않는 공간으로 남게 된다. 가비지가 많이 누적되면 프로그램의 성능에 문제를 일으키게 될 수 있다.

 

 

 


 

동적으로 배열을 할당해주는 것과 그냥 배열로 선언해주는 것의 차이가 뭘까?

 

#include <stdio.h>
#include <stdlib.h>   //malloc 함수를 사용하기 위해선 stdlib 라이브러리를 사용해야함

// int *array = (int *)malloc( 4 * sizeof(int) );

int array;   // 위에 동적할당하는 것을 죽이고 그냥 배열로 선언하는 것이랑 무슨 차이가 있을까?
array[0] = 1;
array[1] = 2;
*(array+2) = 3;

/* 배열 array의 크기가 부족한 상황이 발생한다. */

int *tmp = (int *)malloc( 8 * sizeof(int) );
int i;
for (i=0; i<4; i++)
	tmp[i] = array[i];
    
array = tmp;   // 오류 발생!!!!

}

배열의 이름은 배열의 시작 주소를 저장하는 포인터 변수이다. 단, 그  특성은 값을 변경할 수는 없다는 특성때문에 이 코드가 오류가 발생한다.

 

array = tmp;

다시 말해서, 이 구문에 오류가 발생하는 까닭은 값을 변경할 수 없다는 특성 때문에 오류가 발생한다. 그래서 배열에 동적할당을 사용해주는 것이다.

'💡 자료구조' 카테고리의 다른 글

시간 복잡도와 빅-오 표기법  (0) 2021.06.17
문자열  (0) 2021.06.16
Binary Search vs Linear Search  (0) 2021.06.14
함수의 인자에 대해 알아보기(배열과 포인터)  (0) 2021.06.10
배열의 자료구조 기초  (0) 2021.06.09