Programming/C C++
 1. malloc

C언어에서 동적으로 Memory를 할당하려면 malloc함수를 이용합니다. 이 함수는 인수로 전달된 정수만큼의 byte크기를 Memory에서 할당하고(만일 할당에 실패하면 NULL을 반환합니다.) 할당된 Memory주소를 Pointer로 반환합니다.

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

main()
{
  char *p;
 
  p = (char *)malloc(10);
}


10 byte의 Memory확보 후 해당 Memory위치를 Pointer p에 되돌립니다.

참고 :
malloc()함수사용시 반환부분에 (char *)형으로 변환시켜 주는 이유는 malloc()함수가 Memory를 확보한 후 해당 Pointer를 반환할때 형이 없는 void(*)를 반환하기 때문입니다. 이는 반환되는 Memory영역을 범용적으로 활용하기 위해서 입니다.

malloc()함수를 이용하면 구조체와 결합하여 해당 구조체를 동적으로 할당하고 할당된 구조체를 연결시킴으로서 연결 List를 생성할 수 있습니다.(연결 list라는 것은 같은 데이터형이 기차처럼 연결된 형태를 지닌다고 하여 붙여진 이름입니다.)

다음 Program은 구조체와 malloc()함수를 사용해 동적으로 구조체에 대한 Memory를 할당하고 연결 List를 생성한 예제입니다.

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

main()
{
  struct student{
    char name[5];
    int kuk;
    int eng;
   
    struct student *np;
  };
  struct student *p;
 
  p = (struct student *)malloc(sizeof(struct student));
 
  strcpy(p->name, "kim");
  p->kuk = 80;
  p->eng = 90;
 
  p->np = (struct student *)malloc(sizeof(struct student));
 
  strcpy(p->np->name, "choi");
  p->np->kuk = 90;
  p->np->eng = 100;
 
  printf("%s : kuk - %d, eng - %d\n", p->name, p->kuk, p->eng);
  printf("%s : kuk - %d, eng - %d\n", p->np->name, p->np->kuk, p->np->eng);
  free(p);
  free(p->np);
}


일단 Header File에서 stdlib.h는 malloc()함수 사용을 위해 선언되었으며 string.h는 strcpy()함수 사용을 위해 선언되었습니다.

다음은 구조체 선언부분입니다.

struct student{
    char name[5];
    int kuk;
    int eng;
   
    struct student *np;
};

struct로 구조체가 student라는 이름으로 선언되었습니다. 이 구조체는 학생의 점수관리를 위한 구조체로 학생의 이름과 국어점수 그리고 영어점수를 저장할 수 있도록 name과 kuk, eng Member로 구성되어 있습니다.

그리고 마지막 member에는 struct student *np;가 있는데 이는 자기 자신을 가리키는 Pointer를 Memeber(자기참조 구조체)로 가지기 위해서 존재합니다.

이 자기참조 구조체는 동적으로 같은 구조체가 Memory에서 생성될때 그 구조체의 시작주소를 갖게 됨으로서 자연스럽게 구조체간 연결 List를 이루도록 하는 것입니다.

구조체 선언 다음에는 구조체에 접근하기 위해 해당 구조체 Data형의 Pointer변수를 선언하였습니다.

struct student *p;

구조체와 Pointer를 선언하고 malloc()함수를 호출하여 구조체크기 만큼의 Memory를 동적으로 생성하도록 합니다.

p = (struct student *)malloc(sizeof(struct student));

보시는 바와 같이 malloc함수안에 sizeof함수가 사용되었습니다. 이 sizeof함수는 인수로 student구조체를 전달하고 그 크기만큼의 Byte값을 정수형태로 반환합니다. 그러면 malloc함수는 반환되는 값 만큼 Memory를 확보하고 그 수행 결과로 Memory의 시작주소를 Pointer p에 반환합니다.(이때 반환되는 Data형은 void형이므로 해당 Data형을 student 구조체로 변환해야 합니다.)

이렇게 Pointer p는 student구조체 형식으로 확보된 Memory시작 주소값을 가지게 됩니다.


이제 Pointer p를 이용해 학생의 이름과 점수를 Memory영역에 담아봅시다.

strcpy(p->name, "kim");
p->kuk = 80;
p->eng = 90;

Pointer에서 -> 를 사용하여 각 Member에 접근합니다. 그리고 kim이라는 이름과 국어점수 80점, 영어점수 90점을 저장합니다.

이때 학생은 단 한명이 아니라 2명 세명.. 그 이상도 될지 모르기 때문에 미리 일정한 구조체를 선언해 두는 것은 그리 좋은 선택이 아닐 것입니다. 따라서 이런경우 동적으로 할당한다는 개념이 필요하게 됩니다.

학생수가 늘어나면 그 만큼 더 많은 구조체가 할당되어야 하기 때문에 처음 구조체의 자기참조 구조체에 동적으로 할당한 다른 구조체의 Memory주소를 갖게 함으로서 연결 list형의 구조를 이루도록 하려 합니다.

p->np = (struct student *)malloc(sizeof(struct student));

p->np를 통해 구조체의 np Pointer에 student 구조체 만큼의 Memory영역을 할당하고 해당 Memory의 주소값을 전달하고 있습니다.

이렇게 되면 이전에 할당된 구조체의 np Pointer는 이후에 할당된 구조체의 시작주소를 가지게 됨으로서 연결 List를 이루게 됩니다.


이제 이전 구조체의 Pointer에서 다음 구조체의 Pointer를 통하여 해당 구조체의 Member에 접근해서 이름과 주소를 할당합니다.

strcpy(p->np->name, "choi");
p->np->kuk = 90;
p->np->eng = 100;

그리고 마지막으로 할당된 Memory영역이 더이상 필요가 없어지면 그 Memory영역을 해제하여 그 만큼의 영역을 다시 회수해야 합니다.

free(p);
free(p->np);

free함수를 호출하여 해당 Pointer에 위치한 Memory영역을 해제합니다.

이 작업이 이루어 지지 않으면 쓸데없는 Memory공간을 낭비하게 됩니다.


2. calloc()

calloc() 함수를 이용하면 같은 Data형의 Memory공간을 여러개 배열 형태로 할당할 수 있습니다.

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

main()
{
  char *p;
  int i;
 
  p = (char *)calloc(5, 1);
 
  for (i = 0; i < 5; i++)
    printf("%d\n", p[i]);
}


calloc(5, 1)을 통해 1Byte의 Memory를 5개(0~4)의 배열로 확보하고 해당 Memory시작 주소를 Pointer p에 반환하도록 합니다.

그리고 p[배열인자]형식을 통해 각 배열의 값을 for문으로 돌면서 확인하고 있는데 그 결과는 다음과 같습니다.


참고:
calloc()함수는 Memory를 배열로 확보한고 각 배열의 초기값으로 0을 부여합니다.

이제 확보된 배열의 초기값을 직접 부여하여 그 결과를 확인해 보도록 하겠습니다.

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

main()
{
  char *p;
  int i;
  char cal;
 
  p = (char *)calloc(5, 1);
 
  cal = 'a';
 
  for (i = 0; i < 5; i++)
    p[i] = cal + i;
   
  for (i = 0; i < 5; i++)
    printf("%c\n", p[i]);
  free(p);
}


확보된 각 배열 cal변수에 문자 'a'를 설정하고 for문을 통해 0부터 4까지 문자 'a'에 값을 1씩 더하여(그럼 'b'.. 'c'형태로 변할 것입니다.) 저장한 후 다시 for문을 통해 값을 확인하고 있습니다.


3. free

calloc()함수사용시에도 예외없이 free()함수를 호출하여 사용된 Memory영역을 해제해야 합니다.

사실 malloc()함수나 calloc()함수 사용시에만 free()함수를 쓸 수 있는건 아니고 필요하다면 다른 상황에도 호출하여 사용할 수 있습니다.
0 0