easy software

C언어 malloc을 사용하여 구조체 변수를 동적으로 할당하고 그에 따른 장점을 알아보자 본문

C언어/메모리 관리와 동적 할당

C언어 malloc을 사용하여 구조체 변수를 동적으로 할당하고 그에 따른 장점을 알아보자

JAVA 웹개발자 2015. 2. 21. 16:24

15년 2월 16일에 작성한 구조체 카테고리의

 

'C언어 구조체 배열을 이용한 간단한 도서관리 프로그램' 에서 작성한 코드를 변경하겠습니다.

 

도서관리 프로그램은 길이가 3인 구조체 배열을 두고, 사용자로부터 책 3의 정보를 입력받은 후

 

입력이 모두 끝나면 구조체에 저장된 내용을 출력하는 프로그램이었습니다.

 

그런데 이번글에서는 길이가 3인 구조체 포인터 배열을 두고, 사용자로부터 책 3권의 정보를

 

입력받은 후 구조체 변수를 동적으로 할당하는 형태입니다. 아래 그림과 같은 형태가 됩니다.

 

 

 

우선 코드를 보시고 제 설명을 보시면 조금더 이해가 빨리 될 것 같습니다.

 

그리고 동적할당으로 프로그램을 구현하면 어떠한 장점이 있는지도 설명드리겠습니다.

 

 

 

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


void clearBuffer(void);


//책의 정보를 저장하는 구조체
typedef struct{

    char author[10];//저자
    char name[30];//제목
    int page;//페이지
}book;


int main(void){
    book* b[3]; //구조체 포인터 배열 선언

  

   printf("도서 정보 입력\n");

   for (int i = 0; i < 3; i++)

//heap영역에 공간 확보

      book* pbook = (book*)malloc(sizeof(book) * 1);


      puts("\n");//줄바꿈

      fputs("저자 : ", stdout);
      fgets((*pbook).author, sizeof((*pbook).author), stdin);

      fputs("제목 : ", stdout);
      fgets((*pbook).name, sizeof((*pbook).name), stdin);

      fputs("페이지 수 : ", stdout);
      scanf("%d", &((*pbook).page));

      clearBuffer(); //입력 버퍼를 비우는 함수 호출


      b[i] = pbook;

   }


   fputs("\n\n\n도서 정보 출력\n", stdout);

   for (int i = 0; i < 3; i++){
      printf("\nbook %d \n", i + 1);

      printf("저자 : %s", b[i]->author);
      printf("제목 : %s", b[i]->name);
      printf("페이지 수 : %d \n", b[i]->page);
   }


   //heap영역의 메모리 공간을 정리함
   for (int i = 0; i < 3; i++)
      free(b[i]);

   return 0;
}


//입력 버퍼를 비우는 함수

void clearBuffer(void){
    while (getchar() != '\n');
}

 

 

 

이름이 b인 길이가 3인 구조체 포인터 배열을 선언했습니다.

 

이후에 pbook이라는 변수를 선언해서 heap영역에 할당합니다.

 

그리고 fgets을 이용하여 사용자로부터 책의 정보를 입력받을 때,

 

pbook이 가리키는 구조체 변수에 저장합니다.

 

scanf를 통해 페이지 수를 입력받고 clearBuffer라는 함수를 호출하는데요,

 

fgets는 \n까지 문자열로 입력받지만 scanf는 \n를 제외하고 인식합니다.

 

그렇기 때문에 scanf호출후에는 입력버퍼에 \n이 남아있게 되고, \n을 제거하기 위해

 

clearBuffer함수를 호출하게 되는 것입니다.

 

그리고 b[i]가 pbook을 가리키도록 합니다.

 

3권의 책정보를 모두 저장했다면 printf문을 통해 저장된 정보를 출력해 줍니다.

 

그런데 인자에서 -> 연산자를 볼 수 있는데요, 간단하게 설명하자면

 

b[i]->page 는 'b[i]가 가리키는 page' 라고 해석하시면 됩니다.

 

동일한 뜻은, (*b[i]).page 입니다.

 

출력까지 완료했다면 free함수를 통해서 heap영역을 정리해 줍니다.

 

 

 

동적할당을 함으로써 처음에 구현한 도서관리 프로그램보다

 

이 글에서의 도서관리 프로그램의 장점은 무엇일까요?

 

동적할당을 하지 않을경우에는 100개를 입력받을 것 같다고 하면 100개의 공간을 미리 할당

 

해야 하지만, 동적할당을 하면 필요한 경우에 하나씩 공간을 할당받아 사용할 수 있습니다.

 

그리고 함수의 길이를 길게 잡을 경우, 스택 영역을 벗어나는 오버플로우가 일어 날 수 있습

 

니다. 이럴 경우 구조체 내부가 변경되버리거나 다른 스택 영역의 변수나 함수와 겹치게되면

 

유지보수가 힘들어 진다는 단점이 있기 때문에, 동적할당을 사용하는 것입니다.

Comments