사자자리

[C언어] 7주차 동적 메모리 할당 본문

C언어/C언어 이론

[C언어] 7주차 동적 메모리 할당

renne 2022. 6. 26. 19:36

동적 메모리가 필요한 경우

 - 배열의 크기를 미리 알 수 없을 때

//배열의 크기는 상수로 지정할 수 없다. 컴파일 에러.
int arr[size];

//배열의 최대 크기를 가정해서 할당하면, 메모리 낭비가 발생한다.
int arr[1000];

 

 - 동적 메모리를 사용하면, 원하는 만큼 메모리를 할당할 수 있으므로 메모리 낭비를 최소화할 수 있다.

 - 동적 메모리를 사용하면, 메모리의 할당과 해제 시간을 마음대로 선택할 수 있다.

 

동적 메모리의 할당과 해제

stdlib.h

 - 메모리 관련 함수를 사용하기 위해 필요한 헤더

 

malloc 함수

 - Memory ALLOCation

 - 함수의 인자로 할당할 메모리의 바이트 크기를 입력한다.

 

free 함수

 - 포인터가 가리키는 동적 메모리를 해제한다.

 

#include <stdio.h>
#include <stdlib.h>
int main(){
    int size, sum = 0;
    int *arr = NULL;	//동적 메모리의 주소를 저장할 포인터

    printf("몇 개의 정수를 입력하겠습니까?: ");
    scanf("%d", &size);
    arr = malloc(sizeof(int)*size);	//동적 메모리의 할당

    if (arr == NULL){
        printf("동적 메모리 할당 실패\n");
        return -1;
    }

    printf("%d개의 정수를 입력하세요: ", size);
    for (int i = 0; i < size; i++){
        scanf("%d", &arr[i]);	//동적 메모리의 사용
        sum += arr[i];	//동적 메모리의 주소를 저장하는 포인터 변수는 배열의 원소를 가리키는 포인터처럼 사용한다.
    }
    printf("합계: %d", sum);

    free(arr);	//동적 메모리의 해제
    arr = NULL;	//동적 메모리를 가리키던 포인터 변수에 NULL을 대입하는 것이 안전하다.

    return 0;
}

<실행 결과>
몇 개의 정수를 입력하겠습니까?: 5
5개의 정수를 입력하세요: 1 3 5 7 9
합계: 25

 

동적 메모리와 구조체 포인터 배열

 - 프로그램 실행 중에 구조체를 동적 메모리에 할당하고 그 주소만 포인터 배열에 저장해서 사용할 수 있다.

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

typedef struct rectangle{
    int width, height, area;
} RECT;

int main(){
    int count = 0;
    RECT *arr[100] = {NULL};	//구조체 포인터 배열의 선언

    while(1){
        char choice;
        printf("직사각형을 생성하겠습니까? (Y/N) ");
		scanf("%c", &choice);
		getchar();
        if (toupper(choice) == 'N') break;

        arr[count] = malloc(sizeof(RECT));	//구조체에 대한 동적 메모리 할당
        arr[count] -> width = rand() % 400 + 1;
        arr[count] -> height = rand() % 400 + 1;
        arr[count] -> area = (arr[count] -> width) * (arr[count] -> height);
        count++;
    }

    printf("\n%d개의 직사각형이 만들어졌습니다.\n", count);

    for (int i = 0; i < count; i++){
        printf("%d번째 직사각형의 (가로, 세로, 넓이): (%3d, %3d, %5d)\n", i+1, arr[i] -> width, arr[i] -> height, arr[i] -> area);
    }

    for (int i = 0; i < count; i++){
        free(arr[i]);
        arr[i] = NULL;
    }

    return 0;
}

<실행 결과>
직사각형을 생성하겠습니까? (Y/N) Y
직사각형을 생성하겠습니까? (Y/N) Y
직사각형을 생성하겠습니까? (Y/N) N

2개의 직사각형이 만들어졌습니다.
1번째 직사각형의 (가로, 세로, 넓이): ( 42,  68,  2856)
2번째 직사각형의 (가로, 세로, 넓이): (335, 101, 33835)

 

동적 메모리 관련 함수

void *malloc(size_t size); 동적 메모리를 할당한다
void *calloc(size_t num, size_t size); 동적 메모리 배열(num*size)을 할당하고 0으로 초기화한다
void *realloc(void *memblock, size_t size); 동적 메모리의 크기를 변경해서 재할당한다
void free(void *memblock); 동적 메모리를 해제한다

 

정적 메모리 VS 동적 메모리

  정적 메모리 동적 메모리
메모리 할당 컴파일 시간에 이루어짐 실행 시간에 이루어짐
메모리 해제 자동으로 해제 명시적으로 해제
사용 범위 지역 변수: 선언된 블록 내
전역 변수: 프로그램 전체
프로그래머가 원하는 동안
메모리 관리 컴파일러의 책임 프로그래머의 책임

 


59.6 연습문제: 포인터 연산으로 메모리 주소 조작하기

다음 소스 코드를 완성하여 00000008과 00000014가 각 줄에 출력되게 만드세요.

#include <stdio.h>
int main()
{
    int *numPtrA = NULL;

    printf("%p\n", numPtrA_____);
    printf("%p\n", numPtrA_____);

    return 0;
}

 

정답

#include <stdio.h>
int main()
{
    int *numPtrA = NULL;

    printf("%p\n", numPtrA + 2);	//데이터형이 int이므로 +1할 때마다 4바이트씩 증가한다.
    printf("%p\n", numPtrA + 5);

    return 0;
}
Comments