1 / 20

쉽게 풀어쓴 C 언어 Express

쉽게 풀어쓴 C 언어 Express. 제 17 장 동적 메모리와 연결 리스트. C Express. 이번 장에서 학습할 내용. 동적 메모리 할당에 대한 개념을 이해하고 응용으로 연결 리스트를 학습합니다. 동적 메모리 연결 리스트. 메모리 할당 방법. 정적 (static) 생존 시간 (lifetime): 프로그램 시작  프로그램 끝 실행 중에는 메모리가 일정하게 유지되므로 별도의 관리가 불필요함 자동 (automatic) 생존 시간 : 해당 블록 실행 시작  블록 끝

yazid
Download Presentation

쉽게 풀어쓴 C 언어 Express

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express

  2. 이번 장에서 학습할 내용 동적 메모리 할당에 대한 개념을 이해하고 응용으로 연결 리스트를 학습합니다. • 동적 메모리 • 연결 리스트

  3. 메모리 할당 방법 • 정적(static) • 생존 시간(lifetime): 프로그램 시작  프로그램 끝 • 실행 중에는 메모리가 일정하게 유지되므로 별도의 관리가 불필요함 • 자동(automatic) • 생존 시간: 해당 블록 실행 시작  블록 끝 • 메모리 할당및 해제(반납)가 블록과 연동되어 자동으로 이루어짐 • 실행 시간 스택(runtime stack) 사용 • 동적(dynamic) • 생존 시간: 동적 메모리 할당  동적 메모리 해제 • 프로그래머가 생존 시간 결정 • 힙(heap) 사용 • 정적/자동 메모리 할당의 단점 • 메모리의 크기가 프로그램 시작 전에 결정되어 고정됨 • 예: inta[100]; // 배열의 크기에 변수를 사용할 수 없음 • 결정된 크기보다 더 큰 데이터를 처리할 수 없음 • 결정된 크기보다 작은 데이터를 처리하면 메모리 낭비 유발

  4. 동적 메모리 할당 • 사용자의 요구에 따라 실행 중에메모리 할당 및 해제 • 할당  사용  해제 • 필요한 만큼만 메모리 할당 가능 메모리를 효율적으로 사용 • 라이브러리 함수 사용: <stdlib.h> • 할당: malloc(), calloc() • 재할당: realloc() • 해제: free()

  5. 동적 메모리 할당/해제 함수 void *malloc(size_t size); • size 바이트만큼 동적 메모리 블록 할당 • 반환 값: 성공  동적 메모리 블록 시작 포인터, 실패  NULL • 할당된 메모리 블록은 초기화되지 않음 void free(void *p); • p가 가리키는 동적 메모리 해제 • p가 NULL 포인터이면 무시 malloc • #include<stdlib.h> int *p; p = (int*)malloc(sizeof(int)); // 할당 if (p == NULL) … // 에러 처리 *p = 123; // 사용 free(p);// 해제 p ? free p 123

  6. 예제 #include<stdio.h> #include<stdlib.h> intmain(void) { int*score; inti; score = (int*)malloc(10 * sizeof(int)); if (score == NULL) { fprintf(stderr, "동적 메모리 할당 오류\n"); exit(1); } for (i = 0; i < 10; i++) score[i] = i; for (i = 0; i < 10; i++) printf("%d\n", score[i]); free(score); return0; } 0 1 2 3 4 5 6 7 8 9

  7. 예제 #include<stdio.h> #include<stdlib.h> intmain(void) { char *pc; inti; if (!(pc = (char*)malloc(26 + 1))) fprintf(stderr, "out of memory\n"), exit(1); for (i = 0; i < 26; i++) pc[i] = 'a' + i; pc[i] = '\0'; puts(pc); free(pc); return0; } abcdefghijklmnopqrstuvwxyz

  8. 예제 #include<stdio.h> #include<stdlib.h> #include<string.h> structBook { int number; chartitle[20]; }; int main(void) { struct Book *p; inti; if (!(p = (structBook *)malloc(2 * sizeof *p))) fprintf(stderr, "메모리부족\n"), exit(1); p->number = 1; strcpy(p->title, "C Programming"); (p+1)->number = 2; strcpy((p+1)->title, "Data Structure"); for (i = 0; i < 2; i++) printf("%d: %s\n", p[i].number, p[i].title); free(p); return 0; } 1: C Programming 2: Data Structure

  9. calloc() void *calloc(size_t n, size_t size); • 크기가 size 바이트인 항목 n개를 저장할 수 있는 동적 메모리 할당 • ‘size * n’ 바이트 메모리 할당 • 반환 값: 성공  동적 메모리 블록 시작 포인터, 실패  NULL • 할당된 메모리 블록은 0으로 초기화됨 int *p = (int*)calloc(6, sizeof(int)); int *p = (int*)malloc(6 * sizeof(int)); // 다음은 모두 24B 할당 p = (int*)calloc(6, sizeof(int)); p = (int*)calloc(sizeof(int), 6); • p = (int*)calloc(6 * sizeof(int), 1); • p = (int*)calloc(1, 6 * sizeof(int)); ? ? ? ? ? ? 0 0 0 0 0 0 p p

  10. 예제 0: 96 1: 100 2: 103 3: 116 4: 96 5: 109 6: 89 7: 88 8: 109 9: 94 size = 10, total = 1000 #include <stdio.h>#include <stdlib.h>int main(void) {int *table, size, total, i;    size = 5 + rand() % 6; // size: [5, 10]if (!(table = (int*)calloc(size, sizeof(int))))fprintf(stderr, "out of memory\n"), exit(1);for (i = 0; i < 1000; i++)        table[rand() % size]++;for (total = 0, i = 0; i < size; i++) {        total += table[i];printf("%2d: %3d\n", i, table[i]);    }printf("\nsize = %d, total = %d\n", size, total);    free(table); return0;}      

  11. realloc() void *realloc(void *p, size_t size); • p가 가리키는 동적 메모리의 크기를 size 바이트로 변경 • 메모리 크기가 size 바이트로 증가/감소됨 • 동적 메모리 블록이 다른 위치로 이동될 수 있음 • p가 가리키는 이전 메모리 내용은 변경되지 않음 • 크기가 감소되는 경우에는 감소된 부분만 이전 내용과 동일 • 증가된 부분은 초기화되지 않음 • 반환 값: 성공  동적 메모리 블록 시작 포인터, 실패  NULL • 성공  반환되는 포인터는 p와 다를 수 있음 • 실패  p가 가리키는 이전 메모리 내용은 변경되지 않음 • p가 NULL이면 malloc()과 동일 int *p = (int*)malloc(6 * sizeof(int)); 1 5 7 4 2 9 p 증가 int *q = (int*)realloc(p, 8 * sizeof(int)); int *q = (int*)realloc(p, 4 * sizeof(int)); 1 5 7 4 2 9 ? ? q 1 5 7 4 감소 q

  12. realloc() int *p; • … if (!(p = (int*)malloc(6 * sizeof(int)))) // 에러 처리 … if (!(p = (int*)realloc(p, 8 * sizeof(int)))) //X // 에러 처리 // free(p) 불가능 (p가 가리키던 이전 메모리를 반환할 수 없음) // 메모리 누수(memory leak) 발생 int *p, *q; • … if (!(p = (int*)malloc(6 * sizeof(int)))) // 에러 처리 … if (!(q = (int*)realloc(p, 8 * sizeof(int)))) { //O // 에러 처리 // free(p) 가능 (p가 가리키던 이전 메모리를 반환할 수 있음) } else p = q;

  13. 예제 printf("\nmax size = %uKB\n", max_size);    free(p); return0;}unsignedget_size(void) {return (rand() + 1) * 100;}void job(void *p, unsigned size) {printf("job %p%uKB\n", p, size);// do something} #include <stdio.h>#include <stdlib.h> unsignedget_size(void);void job(void *p, unsigned size); int main(void) {unsignedmax_size = 0, size, i;void *p = NULL, *q; for (i = 0; i < 5; i++) {if ((size = get_size()) > max_size) {printf("realloc%uKB => ", size);if (!(q = realloc(p, size * 1024))) {                puts("failed");                size = max_size;            } else {                puts("succeeded");max_size = size;                p = q;            }        }        job(p, size);    } realloc 4200KB => succeeded job 006D0020 4200KB realloc1846800KB => succeeded job 00AF0020 1846800KB job 00AF0020 633500KB realloc 2650100KB => failed job 00AF0020 1846800KB realloc 1917000KB => failed job 00AF0020 1846800KB max size = 1846800KB

  14. 예제 int *input(int *p_count) {enum { INCR_SIZE = 100 };int *list = NULL, *p, size = 0, count = 0, score;while (scanf("%d", &score) == 1) {if (size <= count) {            size += INCR_SIZE;if (!(p = realloc(list, size * sizeof(int)))) {fprintf(stderr, "out of memory\n");                free(list); exit(1);            }            list = p;        }        list[count++] = score;    }    *p_count = count;return list;} #include <stdio.h>#include <stdlib.h>int *input(int *p_count);int main(void) {int *list, *p, *end, count, sum;    list = input(&count); if (count < 1) {fprintf(stderr, "no data\n"); free(list); exit(1); }    p = list; end = p + count; sum = 0;do { sum += *p; } while (++p < end);printf("average = %g\n", (double)sum / count);    free(list); return0;} 10 20 30 40 50 60 70 80 ^Z average = 45

  15. 연결 리스트 • 배열(array) • 간단하고 다루기 쉬움 • 특정 위치의 원소에 대한 접근이 빠름 • 삽입/삭제가 비효율적 • 연결 리스트(linked list) • 각 원소가 포인터를 사용하여 다음 원소를 가리킴 • 다루기 어렵고 특정 위치의 원소에 대한 접근이 느림 • 삽입/삭제가 용이함 D D B N B C E C E A A 삽입 삭제

  16. 연결 리스트 • 노드(node) = 데이터 필드(data field) + 링크 필드(link field) • 일반적으로 동적 메모리를 사용하여 생성 • 헤드 포인터(head pointer): 첫 번째 노드를 가리키는 포인터 • 자기 참조 구조체(self-referential structure): 멤버 중에 자신과 같은 타입의 구조체를 가리키는 포인터가 있는 구조체 struct node { int data; structnode *link; };

  17. 기본적인 연결 리스트 조작 NODE *p1; p1 = (NODE*)malloc(sizeof(NODE)); p1->data = 10; p1->link = NULL; NODE *p2; p2 = (NODE*)malloc(sizeof(NODE)); p2->data = 20; p2->link = NULL; p1->link = p2; free(p1); free(p2); p2 20

  18. 예제: 책 리스트 if (list == NULL) list = p;elseprev->link = p;        p->link = NULL;prev = p;    } putchar('\n');for (p = list; p != NULL; p = p->link)printf("%s, %d\n", p->title, p->year); for (p = list; p != NULL; p = next)        next = p->link, free(p); return0;}       #include <stdio.h>#include <stdlib.h>#include <string.h> #define SIZE 50 typedefstruct NODE {chartitle[SIZE];int year;struct NODE *link;} NODE; int main(void) {    NODE *list = NULL, *prev, *p, *next;charbuffer[SIZE]; while (1) {printf("책 제목: ");if (!gets(buffer)) break;         p = (NODE*)malloc(sizeof(NODE));strcpy(p->title, buffer);printf("책 출판 연도: ");        gets(buffer);        p->year = atoi(buffer); 책 제목: 컴퓨터 개론 책 출판 연도: 2006 책 제목: C 언어 책 출판 연도: 2007 책 제목: ^Z 컴퓨터 개론, 2006 C 언어, 2007

  19. 예제: 학생 리스트 list.c list.h #include <stdio.h>#include <stdlib.h>#include "list.h" SNODE *make_list(void) {    SNODE node, *p, *head = NULL;while (1) {printf("ID NAME GPA: ");if (scanf("%d%s%lf", &node.id, node.name, &node.gpa) != 3)break;if (!(p = (SNODE*)malloc(sizeof *p)))fprintf(stderr, "out of memory\n"), exit(1);        *p = node;        p->next = head; head = p; // reversed    }return head;} voidfree_list(SNODE *p) {    SNODE *q;for (; p; p = q) { q = p->next; free(p); }} voidout_list(const SNODE *p) {for (; p; p = p->next)printf("%d%s%g\n", p->id, p->name, p->gpa);} // double get_average(const SNODE *p) { ... } #ifndef _LIST_H_#define _LIST_H_#define NAME_SIZE   20typedefstructstudent_node {int id; char name[NAME_SIZE+1]; doublegpa;structstudent_node *next; } SNODE; SNODE *make_list(void);voidfree_list(SNODE *p);voidout_list(const SNODE *p);// double get_average(const SNODE *p);#endif

  20. 예제: 학생 리스트 (계속) #include "list.h"int main() {    SNODE *list;    list = make_list();putchar('\n');out_list(list);//  printf("average = %g\n", get_average(list));free_list(list);return0;} ID NAME GPA: 2013001 강감찬 4.1 ID NAME GPA: 2013002 김유신 4.2 ID NAME GPA: 2013003 이순신 4.3 ID NAME GPA: ^Z 2013003 이순신 4.3 2013002 김유신 4.2 2013001 강감찬 4.1

More Related