C 언어 동적 변수 - C eon-eo dongjeog byeonsu

메모리 동적 할당

메모리 정/동적 할당의 개념과 동적할당함수의 기능과 사용법, 메모리 관리 함수.

  • 학습 목표
    1. 메모리 정적할당과 동적할당의 이해.
    2. 메모리 동적할당함수를 이용하여 프로그램 작성.
    3. 메모리 관리함수의 기능 이해.

주요 용어

  • 데이터 영역 : 전역변수와 static 변수가 저장되는 기억공간 영역.
  • 힙(heap) 영역 : 프로그래머의 필요에 의해 할당과 소멸이 이루어지는 기억공간 영역.
  • 스택(stack) 영역 : 지역변수와 매개변수가 저장되는 기억공간 영역.
  • 메모리 정적할당 : 프로그램이 작성되는 단계에서 기억공간의 크기가 결정되는 기억공간 확보방법.
  • 메모리 동적할당 : 프로그램이 실행되는 중에 입력되는 자료에 따라 기억공간의 크기를 결정할 수 있는 기억공간 확보방법.

메모리 동적할당의 개념

C 언어에서의 기억공간?

  • 프로그램의 실행을 위해 기억공간 필요.
  • 기억공간은 운영체제에서 할당.
  • 할당되는 기억공간의 영역.
    • 데이터 영역.
      • 전역변수와 static 변수가 저장되는 영역.
      • 프로그램이 시작하면서 할당되고, 종료하면 소멸하게 됨.
    • 힙 영역
      • 개발자의 필요에 의해 할당/소멸이 이루어지는 영역.
      • 프로그램이 실행되는 중에 크기가 변함.
      • 메모리 동적 할당에 사용되는 영역.
    • 스택 영역
      • 지역변수와 매개변수가 저장되는 영역.
      • 함수 호출이 완료되면 사라짐.

기억공간의 확보

메모리 정적 할당(Static Allocation)

  • 기억공간의 데이터 영역스택 영역 이용.
  • 프로그램을 작성하는 단계에서 필요한 기억공간의 크기를 결정.

메모리 동적 할장(Dynamic Allocation)

  • 기억공간의 힙 영역 이용.
  • 프로그램 실행 중에 입력되는 자료에 맞게끔 기억공간의 크기를 결정.

메모리 정적할당

  • 변수 선언이나 배열 선언과 같이 프로그램을 작성하는 단계에서 필요한 기억 공간의 크기를 결정.
    • 변수 선언과 같이 할당 시켜줘야 할 기억공간의 한계 크기를 명확히 알고 있을 경우 사용.
    • 메모리 정적 할당은 프로그램이 시작될 때 미리 기억공간의 크기를 고정하여 할당.

메모리 정적할당의 예

#include <stdio.h> void test1(int); void test2(int); // 전역변수로 선언되어 데이터 영역에 할당. // 프로그램 종료될 때까지 존재. int a = 100; void main() { // 지역변수로 스택 영역에 할당. // main()가 종료될 때까지 존재. int b = a; test1(b); test2(b); } // test1이 호출되면, // 매개변수 c와 지역변수 d는 스택영역에 할당. // test1이 종료되면 c, d는 지워짐. void test1(int c) { int d; d = c + 10; printf("%d\n", d); } // test2가 호출되면, // 매개변수 e와 지역변수 f는 스택영역에 할당. // 종료되면 d, f는 지워짐. void test2(int e) { int f; f = e + 20; printf("%d\n", f); } // main()가 종료되면 스택영역에 할당된 b도 제거. // 프로그램이 끝아면 a도 제거.

메모리 정적할당의 장/단점

  • 장점
    • 프로그램에서 사용하게 될 변수의 기억 공간의 크기를 명확히 알고 있다면,
      메모리 정정할당은 쉽게 기억 공간을 사용할 수 있고, 에러의 발생 확률을 줄일 수 있음.
  • 단점
    • 사용하게 될 기억 공간의 크기를 정확히 알지 못하거나, 사용되는 자료의 크기가 각각 차이가 심하다면,
      기억공간의 낭비를 가져오게 됨.

메모리 정적할당의 문제점

#include <stdio.h> void main() { int size; // 배열의 크기를 변수로 선언하면 에러 발생? char a[size]; printf("입력할 문자열의 크기? : "); scanf("%d", &size); printf("주소 : "); scanf("%s", a); printf("입력된 주소 %s\n", a); } #include <stdio.h> #include <stdlib.h> void main() { int size; char *a; printf("입력할 문자열의 크기? : "); scanf("%d", &size); // 메모리 동적할당. a = (char *)malloc(sizeof(char) * size); printf("주소 : "); scanf("%s", a); printf("입력된 주소 %s\n", a); free(a); }

메모리 동적할당 함수

malloc(), calloc(), realloc(), free() 등

메모리 동적할당의 장/단점

  • 힙 영역을 이용하여 프로그램 실행 중에 입력되는 자료의 크기에 맞게 기억 공간 확보.
  • 많은 자료를 처리하는 배열의 크기를 실행 시간에 정의해야 하는 경우에 유용.
  • 프로그램 실행 시 기억 공간의 크기를 지정/재조정 가능.
  • 시간이 지체되는 단점.

메모리 동적할당 순서

  • 기억공간을 동적으로 할당 받을 변수를 포인터를 이용하여 선언.
  • malloc() 등을 이용하여 기억공간을 동적으로 할당 가능.
  • 기억공간의 사용이 끝나면 free()를 이용하여 기억공간 해제.

malloc()

  • 인자로 할당 받고자 하는 기억 공간의 크기를 byte 단위로 전달.
  • 힙 영역에 그 크기만큼 기억 공간을 할당, 할당한 기억공간의 첫 번째 주소 반환.
  • void*로 명시하여 어떤 형이든 형 변환 가능.
  • 초기화 안됨(기억공간의 초기화를 위해서는 memset() 사용).
  • 형식 : void * malloc(size_t, number_of_bytes);
  • 기능 : number_of_bytes에서 주어지는 크기만큼 기억 공간을 동적으로 할당.
  • 예 : void * malloc(sizeof(int));

free()

  • 메모리 해제 함수.
    • 힙 영역에 할당된 공간은 프로그램이 종료될 때까지 유지됨.
    • 할당된 기억 공간을 해제하지 않으면, 공간 부족 현상 발생.
    • 명시적인 반남.
  • 형식 : void free(void *p);
  • 기능 : 동적으로 할당된 기억 공간을 해제할 때 사용.

메모리 동적할당 예 - 1

#include <stdio.h> #include <stdlib.h> void main() { // 1) 동적할당을 위한 포인터변수 선언. int *a; // 2) 기억공간 할당, // - (int *)는 왼쪽의 포인터변수 a와 자료형을 일치시키기 위한 // 강제 형변환. a = (int *)malloc(sizeof(int)); if (a == NULL) { puts("FAILLURE OF ALLOCATION!"); exit(1); } *a = 20; printf("VARIABLE a : %d\n", *a); // 3) 할당받은 기억공간 해제. free(a); }

메모리 동적할당 예 - 2

#include <stdio.h> #include <stdlib.h> #pragma warning(disable : 4996) void main() { // 입력받을 문자 수 저장 변수 선언. int size; // 1) 동적 할당된 기억공간을 연결할 포인터. char *str; printf("INSERT SIZE OF STRING : "); scanf("%d", &size); // 2) 입력 받을 문자 수(size + 1)에 맞게 동적 할당. str = (char *)malloc(size + 1); if (str == NULL) { puts("FAILLURE OF ALLOCATION!"); exit(1); } printf("INSERT STRING : "); // 동적으로 할당된 기억공간에 문자열 저장. scanf("%s", str); printf("STRING THAT SAVED AT DYNAMIC MEMORY : \n%s\n", str); // 3) 할당받은 기억공간 해제. free(str); }

calloc()

  • malloc()와 동일하게 힙 영역에 기억공간 할당.
  • 사용하는 형태와 할당된 기억 공간을 0으로 초기화.
  • 형식 : void * calloc( int n, int size );
  • 기능 : 주어진 size의 크기를 갖는 기억 공간 n개를 할당.
  • 예 : void * calloc( n, sizeof(int));
#include <stdio.h> #include <stdlib.h> void main() { int i; int *a; // int형 크기의 기억공간 5개 할당. a = (int *)calloc(5, sizeof(int)); for (i = 0; i < 5; i++) { // 0으로 초기화 되어 있음. printf("%d\n", a[i]); } free(a); }

realloc()

  • 이미 할당 받은 기억 공간의 크기를 변경해야 할 필요가 있을 때 사용.
  • 형식 : void * realloc( void *p, int size);
  • 기능 : 포인터 p가 가리키고 있는 기억공간의 크기를 지정된 size의 크기로 변경.
int *a; // int형 크기의 5개 기억공간 할당. a = (int *)calloc(5, sizefo(int)); ... // int형 크기의 10개 기억공간 재할당. a = (int *) realloc(a, 10 * sizeof(int));

기억공간 관리함수

memcmp(), memcpy(), memset()

memcmp()

  • 기억 공간에 들어 있는 자료를 주어지는 크기만큼 비교하여, 같은지 여부를 알 수 있게 해주는 함수.
  • 형식 : int memcmp( void *s1, void *s2, size_t n);
  • 기능 : s1, s2가 가리키고 있는 기억 공간의 내용을 n byte 만큼 비교.
    • n바이트만큼 비교하여 s1 > s2 면 양수, s1 < s2 면 음수, s1 == s2 면 0 반환.
#include <stdio.h> // 기억공간 관리함수를 위한 헤더파일. // #include <mem.h> #include <memory.h> void main() { char *s1 = "aaa"; char *s2 = "bbb"; int stat; stat = memcmp(s1, s2, 3); printf("%d\n", stat); }

memcpy()

  • 기억 공간의 자료를 다른 기억 공간 영역으로 복사하기 위한 함수.
  • 형식 : void * memcpy( void *dest, const void * src, size_t n);
  • 기능 : src에서 n byte만큼 dest에 복사.
#include <stdio.h> #include <memory.h> #include <string.h> void main() { char src[] = "1234567890"; char dest[] = "abcdefghijklmnopqrstuvwxyz"; char *stat; printf("BEFORE MEMCPY() DEST : %s\n", dest); // src의 첫 부분에서부터 문자열의 길이(strlen())만큼의 자료를 dest에 복사. stat = (char *)memcpy(dest, src, strlen(src)); if (stat) printf("AFTER MEMCPY() DEST : %s\n", dest); else printf("FAILURE ON MEMCPY()!"); } // BEFORE MEMCPY() DEST : abcdefghijklmnopqrstuvwxyz // AFTER MEMCPY() DEST : 1234567890klmnopqrstuvwxyz

memset()

  • 기억 공간의 자료를 지정한 문자로 채우는 함수.
  • 할당된 기억 공간의 초기화나 내용 삭제를 위해 주로 사용.
  • 형식 : void * memset( void *s, int c, size_t n );
  • 기능 : 포인터 s가 가리키는 곳을 c 값으로 n byte 만큼 채운다.
#include <stdio.h> #include <memory.h> #include <string.h> void main() { char s[] = "1234567890"; printf("BEFORE MEMSET() : %s\n", s); // 배열 s의 데이커를 *로 길이 만큼 채움. memset(s, '*', strlen(s)); printf("AFTER MEMSET() : %s\n", s); }

Toplist

최신 우편물

태그