C(7): Dynamic Memory(malloc)

이규현·2024년 12월 5일

동적 메모리

int* num_array(){
  int i, arr[5];
  for(i=0;i<5;i++){
    arr[i] = i;
  }

  return &arr; 
  // 지역변수이기 때문에 메인에서 호출하기 전 사라진다. 즉 가리키는 주소가 사라짐
  // 이를 해결하기 위해 동적메모리(heap memory)를 사용해야 하는데 이 함수가 malloc
}

int main(){
  int i, *p = num_array();

  for(i=0;i<5;i++)
    printf("%d ", p[i]);
  printf("\n");

  return 0;
}

arr은 지역 변수이기 때문에 호출 전 사라진다. (가리키는 주소가 사라진다)
해결방법
1. static variables
2. global variables
3. Dynamic variables(동적 변수)

위 이미지에서 Heap Memory를 Dynamic Memory라고 부른다.
힙 메모리를 할당 받으려면 malloc 함수를 호출

#include <stdlib.h>
(void *)malloc(size_t size);
typedf unsigned int size_t;

malloc 함수는 매개변수 size를 통해 몇 바이트를 원하는지 입력 받아 운영체제로부터 그만큼의 Heap Memory를 할당 받은 후에 시작 주소를 돌려준다.

malloc 함수는 void* 타입의 포인터를 리턴

int* get_number(){
  int *p;
  p = (int*)malloc(sizeof(int));
  if(p != NULL){
    *p = 20;
  }
  return p;
}

int main(){
  int i, *ptr;
  ptr = get_number();
  printf("*ptr: %d.\n", *ptr);
  free(ptr);
  ptr = NULL;
  return 0;
}

get_number 함수를 호출해 리턴 받은 포인터를 따라가 값을 찍음.
get_number 의 리턴 값인 p가 가리키는 공간은 malloc에 의해 만들어진 Heap Memory.
스택 메모리와 달리 힙 메모리는 함수가 끝나도 사라지지 않는다.

malloc에 의해 만들어지는 공간은 기본적으로 프로그램 실행 도중 확보한 공간이다.

malloc으로 할당받은 메모리는 free를 가하기 전까지 그대로 살아있다.

사용예제

#define MAX 10

int* square_array(){
  int i;
  int *p = NULL;

  p = (int*)malloc(MAX * sizeof(int));
  if(p != NULL){
    for(i=0; i< MAX; i++){
      p[i] = i*i;
    }
  }
  return p;
}

int main(){
  int i, *arr = square_array();
  for(i=0; i< MAX; i++)
    printf("%d ", *(arr+i));
  printf("\n");
  free(arr);
  arr = NULL;

  return 1;
}
result: 0 1 4 9 16 25 36 49 64 81

malloc, calloc, realloc에 의해 동적배열 만들 수 있다.

calloc

int *p = (int*)calloc(3*sizeof(int));

calloc의 경우 malloc과 마찬가지로 힙 메모리를 할당하고 메모리가 없으면 NULL을 돌려준다.
차이점: calloc은 할당된 메모리 요소를 자동으로 0으로 초기화

realloc

int *p = (int*)calloc(3*sizeof(int));
int *new_p = (int *)reaclloc(p, 5*sizeof(int));

다시 할당하라는 뜻.
malloc으로 정수공상 3개를 할당했는데 부족할 경우 realloc함수를 통해 다섯개의 공간을 만들어달라고 요구할 수 있음.

사용예제

int main() {
  int *p = (int*)malloc(3 * sizeof(int));
  int i;

  p[0] = 100; p[1] = 200; p[2] = 300;
  
  p = (int *)realloc(p, 5 * sizeof(int));
  if(p != NULL){
    p[3] = 400;
    p[4] = 500;
  }

  for(i = 0; i < 5; i++){
    printf("%d ", *(p+i));
  }
  printf("\n");

  free(p);
  p = NULL;

  return 0;
}

문자열 읽기 예제

int main() {
  int last = 0; char ch;
  char *p;

  p = (char *)malloc(sizeof(char));
  if(p == NULL)
    exit(1);

  printf("Enter a character string.\n");
  while(1){
    if((ch = getchar()) == '\n')
      break;
    else{
      *(p+last) = ch;
      last++;
      p = (char*)realloc(p, (last+1)*sizeof(char));
      if(p == NULL)
        exit(1);
    }
  }

  *(p+last) = '\0';
  printf("%s\n", p);

  free(p);
  p = NULL;

  return 1;
}
실행 결과: 
Enter a character string.
The beauty of programming
The beauty of programming

문자를 읽을 때마다 배열의 크기를 늘리며 동적 배열에 저장하는 프로그램.

문자 하나하나를 읽으면서 그때마다 realloc에 의해 동적 배열의 크기를 하나씩 늘린다.

if문: 입력 첫 문자가 '\n'이라면 그 곳에 NULL문자 삽입.

배열 마지막 인덱스에 1을 더한 것이 배열 요소의 개수 -> 필요한 공간의 크기는 (last + 1)

0개의 댓글