18 동적할당과고급처리 인터넷정보과 1
2/19 동적할당 목적 다음과같은일반변수의선언과사용은변수를정적 (static) 으로사용 int a = 10; 메모리사용예측이부정확한경우는충분한메모리를미리확보해야하는것은비효율 동적 (dynamic) 메모리할당 (Memory Allocation) 동적인메모리할당을위해서는함수 malloc() 을이용, 메모리공간을확보 함수 malloc() 은 stdlib.h 헤더파일에다음함수원형으로정의 함수 malloc() 은인자로메모리할당의크기를지정하고, 반환값으로할당된메모리의시작주소를반환 반환값의유형은모든자료형의포인터로이용할수있는 void *
함수 malloc() 정수형 int 의메모리공간을함수 malloc() 을이용하여동적으로할당하는소스 확보된공간의주소는 int * 의변수에저장하여간접연산자 *pi 를이용하여원하는값을저장 다음은위문장으로메모리에 4 바이트가할당된모습 3/19 Check! 중간점검 1
메모리해제 함수 malloc() 에의하여동적으로할당된메모리공간은더이상필요가없거나, 프로그램을종료하는경우에반드시메모리를해제 함수 free() 는 stdlib.h 헤더파일에다음함수원형으로정의 void free(void *) 함수 malloc() 의반환주소를저장한변수 pi 를해제하려면다음과같이기술 free(pi); 함수 free() 는인자로해제할메모리공간의주소값을갖는포인터를이용하여호출 함수 free(pi) 가호출되어성공적으로메모리가해제되면변수 pi 는 NULL 값을가지며더이상 4 바이트의공간은사용불가능 4/19
배열과같은메모리할당 자료형 int 배열과같이 int 형메모리공간을한번에여러개동적으로확보 int *ary; ary = (int *) malloc( sizeof(int)*3 ); 함수 malloc() 이반환하는값은포인터인 int * 의변수로저장하고, malloc() 의인자는 sizeof(int) * ( 확보하려는배열의원소의개수 ) 로지정 메모리공간이성공적으로확보되면변수 ary 를이용하여다음과같이배열을이용 ary[0] = 10; ary[1] = 11; ary[2] = 12; 위문장이실행된이후의메모리의모습은다음 확보하여이용하던배열도사용할필요가없으면함수 free() 를이용, 해제 free(ary); 5/19 프로그램실행중에동적으로확보된메모리는프로그램이종료되기전에반드시해제
함수 calloc() 함수 calloc() 은메모리공간을확보하면서초기값을 0 으로저장 인자 함수 malloc() 은메모리공간을확보하고그장소에초기값을저장하지않음 함수 calloc() 은함수원형이 stdlib.h 헤더파일에정의 함수 calloc() 에서앞의인자는배열의개수, 뒤의인자는한원소의크기 int *ary; ary = (int *) calloc( 3, sizeof(int) ); 함수 calloc() 을위와같이사용하면변수 ary 는 int 형원소 3 개를확보한저장공간을기본값 0 으로저장 6/19
함수 realloc() 함수 realloc() 은이미확보한저장공간을새로운크기로변경 void * realloc(void *, size_t); 인자 함수 realloc() 의첫번째인자는변경할저장공간의주소이며, 두번째인자는변경하고싶은저장공간의크기 함수 realloc() 에서첫번째인자가 NULL이면함수 malloc() 과같은기능을수행, 즉지정된크기만큼의새로운공간을할당 int *reary, *cary; cary = (int *) calloc( 3, sizeof(int) ); 7/19 Check! 중간점검 2,3
자기참조구조체 구조체정의 자기참조구조체 struct selfref { int n; struct selfref *next; }; 자기참조구조체란구조체의멤버변수중의하나가자기자신의구조체포인터변수를갖는특수한중첩된구조체 멤버 next 의자료형을포인터가아닌 struct selfref 로한다면컴파일시간에에러발생 구조체정의구문에서아래와같이자기자신구조체유형멤버는허용하지않음 struct selfref { int n; struct selfref next; }; 8/19
9/19 리스트 링크트리스트 ( 연결리스트 : Linked List) 자기참조구조체는반드시구조체의멤버변수중의하나가자기자신의구조체포인터변수이어야함 자기참조구조체는동일구조체의표현을여러개만들어연결할수있는기능이가능 이러한구조를연결리스트 (Linked List) 라함 간단히두개의구조체를연결하는방법 우선구조체 struct selfref 를하나의자료형인 list 형으로 정의 typedef struct selfref list; 자료형 list 포인터형인 first 와 second 를선언 list *first = NULL, *second = NULL;
10/19 연결리스트만들기 두구조체포인터변수에함수 malloc() 을이용하여구조체의멤버를저장할수있는저장공간을할당 first = (list *) malloc( sizeof(list) ); second = (list *) malloc( sizeof(list) ); 두구조체에 first, second 에각각정수 100, 200 을저장하고, 구조체 second 의멤버 next 에는 NULL 을저장 first->n = 100; second->n = 200; second->next = NULL; 다음은위문장이실행된이후의메모리그림 구조체 first 의멤버 next 에는아직아무값도저장하지않은상태
연결리스트만들기 위그림으로는아직구조체 first 와 second 는아무관련이없음 만일구조체 first 가다음 second 구조체를가리킨다는의미의코딩을원한다면다음문장이필요 first->next = second; 즉구조체 first 의멤버 next 에구조체 second 의주소값을저장 다음은이문장이실행된후의메모리모습 11/19 이러한자기참조구조체의표현은프로그램에서자주이용되는자료구조로프로그램에서는매우중요한구조
연결리스트 프로그램언어 C, C++, Java 를개발된순서로나열해보자. 이러한표현에서가장많이이용하는방법중의하나가다음과같은표형태 1 C 2 C++ 3 Java 12/19 이러한순차적 (sequential) 자료에가장적합한메모리의구조 위와같이순차적자료항목을표현하는가장쉬운방법은배열 자기참조구조체를이용한연결리스트 (Linked List) 구조도순차적자료에적합 위그림이위자료를연결리스트로표현한그림 각각의사각형은한항목의자료를표현하는것으로노드 (node), 항목 (item) 또는원소 (element) 라부름 헤드 (head) 포인터는연결리스트의처음노드를가리키는포인터 연결리스트의가장큰장점 연결리스트항목의수를프로그램내부에서메모리가허용하는한늘릴수있다는것
13/19 노드구조체 연결리스트를구현하려면자기참조구조체를이용 연결리스트의헤드포인터는연결리스트의첫번째원소를가리키며, 각각의원소는자기다음의원소를가리킴 연결리스트의마지막원소는 NULL 값을가지고있어마지막원소임을알수있음 위의자료를표현하는구조체 struct linked_list 를정의 구조체 struct linked_list 의멤버로는 문자열을저장할 char * 변수인 name, 그리고다른구조체를가리킬포인터 next 로구성 문장 typedef 를이용하여 struct linked_list 를간단히 NODE 로정의하고, 이 NODE 의포인터를 LINK 로정의 struct linked_list { char *name; struct linked_list *next; }; typedef struct linked_list typedef NODE * NODE; LINK;
구조체노드생성 구조체 NODE 에 Java 문자열을저장하는모듈 우선새로생성할노드의주소를저장할변수 cur 를선언 LINK cur; char str[] = Java ; cur = (NODE *) malloc(sizeof(node)); if (cur == NULL) { printf(" 노드생성을위한메모리할당에문제가있습니다.\n"); return NULL; } 변수 cur 가가리키는구조체의멤버 name 은문자포인터 이 cur->name 에저장할문자의수만큼메모리를할당 cur->name = (char *) malloc(sizeof(char)*(strlen(str)+1)); 함수 strcpy() 를이용하여 Java 가저장된문자열 str 을 cur->name 에복사 strcpy(cur->name, str); 14/19 현재생성된노드의멤버 cur->next에는초기에 NULL을입력한후, 필요하면나중에다른구조체를가리키도록대입 cur ->next = NULL; Check! linkedlist.c
#if 와 #elif C 언어의조건문과같은전처리기지시자 #if 와 #elif 를제공 #if 다음에는괄호가없이상수수식이오며, 관계연산자나논리연산자를이용가능 #if 는다음수식의결과가 0 이아니면참으로인식 #if SYSTEM == WINDOWS #include "stdio.h" #endif #if 는조건식이참이면 #endif 가나올때까지사이의문장을실행 #if 는다음과같이 #elif 와 #else 도제공 #if SYSTEM == WINDOWS #include "stdio.h" #elif SYSTEM == MAC #include "vax.h" #elif SYSTEM == UNIX #include "unix.h" #else #include "etc.h" #endif 15/19
16/19 #ifdef #ifdef 는다음에나오는기호상수가정의되어있으면 #endif 까지의문장을실행하고, 그렇지않으면소스에서제거 #ifdef 는반드시 #endif 로종료해야 #define DEBUG #ifdef DEBUG if (i%5 == 0) printf("debug : 1 부터 %d 까지의곱은 %d 입니다.\n", i, prod); #endif 위문장은기호상수 DEBUG 가정의되어있으므로 #ifdef 내부의 if 조건문을포함하여컴파일을실행 만일 #define DEBUG 문장이없다면 #ifdef 내부의 if 조건문은소스에서제거되므로컴파일에참여할수없고, 당연히실행해도그부분은실행되지않음
#ifndef #ifndef 는 #ifdef 와반대 #ifndef 기호상수가정의되어있지않으면 #endif 까지의문장을전처리기에서실행하고, 기호상수가정의되어있으면전처리기에서실행하지않고소스에서제거 #ifndef 도반드시 #endif 로종료 #ifndef LIMIT #define LIMIT 20 #endif 17/19
18/19 프로그래밍실습 프로그램목적 주어진문자열을배열에저장하고, 이배열을알파벳문자순서로나열하는프로그램 파일 내용 sort.c 함수 main() 을구현한소스 조건 sortlib.c sort.h 함수 sort(), prtarray(), swap() 을구현한소스 이프로그램에서필요한헤더파일과열거형, 함수원형을정의한헤더파일 10 개의문자열을 char *pl[10] 에선언 ("cobol", "pascal", "java", "c#", "c", "c++", "smalltalk", "basic", "fortran", "b") 을저장 문자열순서가작은것부터나열하는오름차순과그반대인내림차순으로정렬 함수는 main() 과함수 sort(), prtarray(), swap() 으로구성
프로그램 : 프로그래밍수정실습 P 669 예제 listlib.c 에리스트의맨처음에노드를끼워넣는 insert(link head, LINK cur) 추가하여 listlib2.c 로저장하기 deletenode(link prev, LINK cur) 추가하기 19/19