본문 바로가기
카테고리 없음

malloc 동적할당 / 정적할당

by MEHAVING 2019. 9. 26.
반응형

정적할당 / 동적할당

1) static 정적할당

프로그램이 시작되면 변수의 저장공간을 먼저 할당하고 프로그램이 종료되면 저장공간을 해제

→ 처음 고정된 메모리의 크기 때문에 메모리를 유연하게 사용하지 못해 많은 문제가 발생한다

 

사이즈가 확실해야 작동 가능

ex) 배열 #define SIZE 10으로 정해주거나 직접 숫자를 입력해 사이즈 정해주어야 함

 

 

2) malloc 동적할당 ( dynamic memory allocation )

프로그램이 실행되는 중에 필요할 때 필요한만큼 메모리를 운영체제로부터 저장공간을 할당받아서 사용하고 사용이 끝나 메모리가 필요 없을 때 저장공간을 해제해 시스템에 메모리를 반납하는 것

 

=> 더 유연하고 효율적이게 메모리를 사용하고 관리 가능

 

전역변수와 지역변수로 해결이 되지 않는 상황

생성과 소멸의 시기가 지역변수나 전역변수와 다른 유형의 변수 malloc과 free

함수가 매번 호출될 때마다 새롭게 할당되고 또 함수를 빠져나가도 유지가 되는 유형의 변수

 

 

동적메모리가 할당되는 공간: 히프(heap) / 운영체제가 사용되지 않는 메모리 공간을 모아 놓은 곳

 

    int *p;
    p = (int *)malloc(sizeof(int)); //int형 바이트 크기 만큼 동적 메모리 할당하고 시작 주소를 p로 초기화
    *p = 1000; // p가 가르키는 장소에 1000 저장
    free(p); //동적 메모리 반납

- malloc()함수 : size바이트 만큼의 메모리 블록을 할당, 동적 메모리 블럭의 시작 주소를 반환

- 동적메모리는 포인터로만 사용할 수 있음

- free()함수 : 할당된 메모리 블록을 운영체제에게 반환, 해제

 

** malloc()은 시스템의 메모리가 부족해서 요구된 메모리를 할당할 수 없으면 NULL을 반환한다. 따라서 malloc()의 반환값은 항상 NULL인지 검사하여야 한다.

 

#include <stdio.h>
//동적 메모리를 사용하기 위해 필수적으로 넣어야하는 라이브러리
#include <stdlib.h>

int main()
{
    int *pi; //Pointer Integer
    // integer Pointer로 형변환을 해주고 pi라는 변수가 해당 위치를 기억하게 해주는 것
    pi = (int *)malloc(sizeof(int)); //malloc : 메모리를 () 크기만큼 할당하여라

    if(pi == NULL ) //동적 메모리 할당이 실패하면
    {
        printf("동적 메모리 할당을 실패했어요.\n");
        exit(1);
    }
    *pi = 100;
    printf("%d\n", *pi);
    // 동적메모리 사용 이후 무조건 해당 메모리 반환
    free(pi); //메모리 할당을 해지한다


    return 0;
}

 

사이즈가 정해져있지않은 배열을 사용하기 위해서 사용한다

ex) p = (int *)malloc(SIZE * sizeof(int));

malloc은 포인터를 사용해야 한다

p[i] 포인터의 인덱스 or *(p+i) : int의 배열이므로 주소값은 4Byte씩 늘어난다 즉, 배열의 사이즈만큼 주소값도 이동한다

 

동적메모리로 알파벳 출력

#include <stdio.h>
//동적 메모리를 사용하기 위해 필수적으로 넣어야하는 라이브러리
#include <stdlib.h>

int main()
{
    char *pc = NULL;
    int i=0;
    //하나의 문자가 들어갈 수 있는 1Byte 공간 100개가 할당 / pc포인터를 통해 들어갈 수 있므
    pc = (char *)malloc(100*sizeof(char));

    if(pc == NULL){
        printf("동적 메모리 할당에 실패했습니다.\n");
        exit(1);
    }
    //pc가 가르키는 포인터를 1씩 증가시키며(주소값 like 배열) 알파벳 소문자를 삽입
    for(i=0; i<26; i++){
        *(pc+i) = 'a' + i; //'a' 아스키코드
    }
    // 아스키 코드 0은 NULL, 마지막 문자로 NULL을 넣어준다
    *(pc+i)=0;
    // null값을 만날때까지 문자열 출력
    printf("%s\n", pc);
    // 동적메모리 할당 해제
    free(pc);
    return 0;
}

 

#include <stdio.h>
//동적 메모리를 사용하기 위해 필수적으로 넣어야하는 라이브러리
#include <stdlib.h>

int main()
{
    int *pi, i;
    pi = (int *)malloc(5*sizeof(int));
    if(pi == NULL){
        printf("동적 메모리 할당에 실패했습니다.\n");
        exit(1);
    }
    pi[0] = 100;
    pi[1] = 200;
    pi[2] = 300;
    pi[3] = 400;
    pi[4] = 500;
    //주소값에 위치한 값 하나씩 출력
    for(i=0; i<5; i++){
        printf("%d\n", *(pi+i));
    }
    // 동적할당 해제
    free(pi);
    return 0;
}

cf) calloc과 malloc의 차이

malloc void *malloc(sizeof(int)*3);
=> 반환형이 void기 때문에 int로 초기화 (int*)malloc(sizeof(int)*3); 
calloc void *calloc(3, sizeof(int));
=> (int*)calloc(3, sizeof(int)); 요소의 개수와 크기를 받음

malloc 및 calloc은 할당하고자 하는 메모리 크기를 바이트 단위로 할당할 수 있는 함수

 

malloc 은 할당을 하게되면 값들이 쓰레기값이 들어가있고,

calloc은 값이 0으로 초기화 됩니다.

realloc은 이미 할당되어 있는 메모리의 크기를 바꿀때 사용

 

동적배열스택

typedef int element;
typedef struct {
	element *data;		// data은 포인터로 정의된다. 
	int capacity;		// 현재 크기
	int top;
} StackType;

 

스택은 그때그때 크기를 고칠 수 없기 때문에 크기인 capacity를 유연하게 다루기 위해 구조체 생성

 

 

realloc은 메모리에 공간이 있으면 새로운 공간을 만들어 붙히고 자료들의 자리도 새로운 공간으로 옮겨준다

 

 

컴퓨터는 후위표기식(연산자를 뒤로 보내는 것)으로 해석해 실행시킨다

사용자는 중위표기법으로 표기, 연산자 우선순위 중요

 

 

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

int main(void)
{
    int *pList = NULL, i = 0;

    pList = (int*)malloc(sizeof(int)* 3); //12바이트 3*int형 4바이트를 동적할당 하고 시작주소를 pList포인터 변수에 저장
    //malloc 함수의 반환 자료형은 void 이기 때문에 int*형으로 형변환

    pList[0] = 10; // *(pList + 0) = 10; 과 같음
    pList[1] = 20;
    pList[2] = 30;

    for(i=0; i<3; i++)
    {
        printf("%d\n", pList[i]);
    }

    free(pList);

    return 0;
}
반응형

댓글