본문 바로가기
지식/자료구조

[자료구조] 동적 할당 배열 (Dynamically Allocated Arrays)

by 천무지 2024. 4. 7.
반응형

 

<One-dimensinal arrays>

동적 할당을 통해 배열을 선언하는 방법을 알아보겠습니다.

이 방법은 프로그래밍을 하다가 아직 배열의 크기를 정하지 못했을 때 유용하게 사용할 수 있습니다.

 

일반적으로 우리는 다음과 같이 배열을 사용합니다.

#define MAX_SIZE 100
void main()
{
    int i, n, data[MAX_SIZE];
    printf("How many integers do you want to generate? ");
    scanf("%d", &n);
    for (i = 0; i < n; i++)
    {
        data[i] = rand();
        printf("%d\n", data[i]);
    }
}

 

이렇게 배열을 사용한다면 몇 가지 단점이 존재합니다.

1. 만약 int형 자료의 수가 100보다 작으면 메모리의 낭비.

2. 만약 int형 자료의 수가 100보다 많으면 프로그램일 비정상적으로 작동.

 

이때 사용하면 좋은 방법은 배열을 동적으로 할당해 주는 것입니다.

배열의 메모리 할당을 run time 중에 해주는 것이죠. 

void main()
{
    int i, n, *data;
    printf("How many integers do you want to generate? ");
    scanf("%d", &n);
    data = malloc(n * sizeof(int));
    for (i = 0; i < n; i++)
    {
        data[i] = rand();
        printf("%d\n", data[i]);
    }
    free(data);
}

 

이때 malloc이라는 함수를 사용합니다.

void* malloc(size_t size)

- size byte 만큼 메모리를 할당하고 메모리의 시작 주소를 반환합니다.

 

★주의 할 점!!: 만약 malloc을 사용하였다면 반드시 메모리를 해제 또한 해주어야 합니다. 그렇게 하지 않는다면 프로그램이 종료후에도 메모리가 그대로 남아있기 때문입니다.

 

 

 

다음으로 알아볼 것은 realloc입니다. 이 함수는 동적 할당 된 메모리를 다시 원하는 크기에 맞게 재할당할 수 있게 해주는 함수 입니다.

 

먼저 1차원 배열을 통해 알아보겠습니다.

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

void main() {
  int i, n, m, *data;
  printf("How many integers do you want to generate? ");
  scanf("%d", &n);
  data = malloc(n*sizeof(int));
  printf("memory allocated at %p\n", data);
  for(i=0; i<n; i++) 
    data[i] = rand()%100;
  printf("How many integers do you want to generate additionally? ");
  scanf("%d", &m);
  data = realloc(data, (n+m)*sizeof(int));
  printf("memory reallocated at %p\n", data);
  for(i; i<n+m; i++) 
    data[i] = rand()%100;
  for(i=0; i<n+m; i++) 
    printf("%3d: %8d\n", i+1, data[i]);
  free(data);
}

 

현제 int형을 n개 만큼 동적 할당 받은 data 배열이 있습니다. 그리고 난 뒤 다시 m을 입력받아 int형을 (m+n)개 만큼 할당 받았습니다.

 

만약 추가적인 메모리를 할당하면서 처음 배열의 메모리 공간 뒤에 공간이 충분히 남아있다면 그 뒤에 m개 만큼 배열을 할당합니다. 하지만 처음 배열의 메모리 공간 뒤에 공간이 충분치 않아 m개의 배열을 할당하기 어렵다면 새로운 공간을 할당받고 배열의 데이터는 세로운 공간으로 모두 복사됩니다.

 

저는 현재 메모리 공간이 이주된 것을 볼 수 있습니다.

 


<Two-dimensinal arrays>

 

이번에는 동적 할당을 통해서 2차원 배열을 만들어 보겠습니다.

먼저 2차원 배열은 일반적으로 다음과 같이 선언합니다.

int x[3][5];

마치 행렬과 같습니다.

 

하지만 우리는 동적 할당에 관심이 있기 때문에 동적 할당으로 바로 들어가봅시다.

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

int** make2dArray(int, int);

void main() {
    int i, j;
    int **matrix;

    matrix = make2dArray(5, 5);

    for(i = 0; i < 5; i++) {
        for(j = 0; j < 5; j++) {
            matrix[i][j] = i*5 + j + 1;
            printf("%p: %2d ", &matrix[i][j], matrix[i][j]);
        }
        printf("\n");
    }

    /* free memory */
    for(i = 0; i < 5; i++) 
        free(matrix[i]);
    free(matrix);
}

int** make2dArray(int rows, int cols) {

    int **x, **y, i;

    /* allocate memory for row pointers */
    x = malloc(rows*sizeof(*x));
    printf("x allocated at address %p\n\n", x);

    printf("\n%d\n\n", sizeof(x[0]));

    /* allocate memory for each row */
    for(i = 0; i < rows; i++)  {
        x[i] = malloc(cols*sizeof(**x));
        printf("x[%2d] allocated at address %p\n", i, x[i]);
    }

    return x;
}

 

make2dArray라는 함수가 2차원 배열을 만들고 있습니다.

내부적으로 한번 들어가서 알아보겠습니다.

먼저 x는 이중포인터로 선언되었습니다.

이후에 x에 동적 할당을 하게 되는데 int형 포인터 변수 크기만큼 rows개를 할당합니다. 이후에 새롭게 생성된 rows 개의 int형 포인터 변수들에 각각 cols개의 int 형 배열을 선언하여 2차원 배열을 만드는 것입니다.

동작 방식은 일반적은 2차원 배열과 같습니다.

 

동적으로 할당 받은 2차원 배열 또한 메모리를 해제 해주어야합니다.

하지만 동적 할당을 받은 순서의 역순으로 다시 해제를 해줍니다.

/* free memory */
    for(i = 0; i < 5; i++) 
        free(matrix[i]);
    free(matrix);

 

반응형