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

Slides:



Advertisements
Similar presentations
스택 스택 추상자료형 스택 스택의 구현 스택의 응용 한빛미디어(주).
Advertisements

프로그래밍1 및 실습 (C언어) - 3장 기본자료형 (3.6부터 끝까지) -
2007 1학기 12 배열.
제 3 장 변수와 자료형.
Linux/UNIX Programming APUE (The Environment of a UNIX Process)
슬라이드 1~21까지는 각자 복습! 슬라이드 22부터는 수업시간에 복습
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
Internet Computing KUT Youn-Hee Han
제 8 장  파서 생성기 YACC 사용하기.
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2011
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2005
제 2 장 배열과 스트링.
Internet Computing KUT Youn-Hee Han
쉽게 풀어쓴 C언어 Express 제18장 입출력과 라이브러리 함수 C Express.
C 11장. 포인터의 활용 #include <stdio.h> int main(void) { int num;
Chapter 03 배열, 구조체, 포인터.
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
처음으로 배우는 C 프로그래밍 제2부 기초 제5장 반복문.
쉽게 풀어쓴 C언어 Express 제16장 파일 입출력 C Express Slide 1 (of 23)
CHAP 3:배열, 구조체, 포인터.
head data link data link data link NULL a b c
자료 구조: Chapter 3 (2)구조체, 포인터
Chapter 9 – 구조형과 리스트 처리 Outline 9.1 자신 참조 구조형 9.2 선형 연결 리스트 9.3 리스트 연산
연산자 대입 연산자 산술 연산자 관계 연산자 논리 연산자 비트 연산자 콤마 연산자 축약 연산자 sizeof 연산자
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
10장 메모리 관리.
쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express.
25장. 메모리 관리와 동적 할당.
동적메모리와 연결리스트 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
[INA240] Data Structures and Practice
3장. 포인터, 배열, 구조체 포인터, 배열, 구조체 학습목표 기본적 데이터 타입
C 7장. 배열과 문자열 #include <stdio.h> int main(void) { int num;
기초C언어 제3주 C프로그램 구성요소, 변수와 자료형 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원
Dynamic Memory and Linked List
7장 배열 배열의 정의 배열의 초기화 1차원 배열 2차원 및 다차원 배열 문자 배열 배열과 구조.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
쉽게 풀어쓴 C언어 Express 제10장 배열 C Express.
6장 배열.
14주차.
제 3 장 상수와 변수
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
쉽게 풀어쓴 C언어 Express 제7장 반복문 C Express.
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
4장 제어문 선택문: if 문, if – else 문, switch 문
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
개정판 누구나 즐기는 C언어 콘서트 제6장 반복문 출처: pixabay.
Memory & Data Management.
배열과 연결리스트 연결리스트 배열 메모리 할당이 연속적이어서 인덱스 사용시 검색이 빠르다.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
함수와 변수 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
제어문 & 반복문 C스터디 2주차.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Chapter 11. 배열과 포인터.
#1 배열 활용 #include int main(void) { int i; int grade[5]; grade[0] = 10; grade[1] = 20; grade[2] = 30; grade[3] = 40; grade[4] = 50; for(i=0;i.
-Part2- 제1장 1차원 배열이란 무엇인가.
6장 반복제어문 for 문 while 문 do while 문 기타 제어문.
-Part1- 제7장 반복문이란 무엇인가.
자료구조 (Data Structure).
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express Slide 1 (of 28)
토론을 위한 질문 배열의 이름에는 무엇이 저장되는가? C언어에서 배열 추상데이터의 store는 어떻게 구현 되는가?
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express.
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
어서와 C언어는 처음이지 제16장.
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
어서와 C언어는 처음이지 제22장.
개정판 누구나 즐기는 C언어 콘서트 제12장 파일 입출력 출처: pixabay.
Presentation transcript:

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

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

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

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

동적 메모리 할당/해제 함수 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

예제 #include <stdio.h> #include <stdlib.h> int main(void) { int *score; int i; 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); return 0; 1 2 3 4 5 6 7 8 9

예제 #include <stdio.h> #include <stdlib.h> int main(void) { char *pc; int i; 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); return 0; } abcdefghijklmnopqrstuvwxyz

예제 #include <stdio.h> #include <stdlib.h> #include <string.h> struct Book { int number; char title[20]; }; int main(void) { struct Book *p; int i; if (!(p = (struct Book *)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

calloc() void *calloc(size_t n, size_t size); 크기가 size 바이트인 항목 n개를 저장할 수 있는 동적 메모리 할당 ‘size * n’ 바이트 메모리 할당 반환 값: 성공  동적 메모리 블록 시작 포인터, 실패  NULL 할당된 메모리 블록은 0으로 초기화됨 p ? 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)); p int *p = (int*)calloc(6, sizeof(int));

예제 #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); return 0; }       0: 96 1: 100 2: 103 3: 116 4: 96 5: 109 6: 89 7: 88 8: 109 9: 94 size = 10, total = 1000

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

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;

예제 #include <stdio.h> #include <stdlib.h> unsigned get_size(void); void job(void *p, unsigned size); int main(void) { unsigned max_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); }     printf("\nmax size = %uKB\n", max_size);     free(p); return 0; } unsigned get_size(void) {     return (rand() + 1) * 100; } void job(void *p, unsigned size) {     printf("job %p %uKB\n", p, size);     // do something } realloc 4200KB => succeeded job 006D0020 4200KB realloc 1846800KB => succeeded job 00AF0020 1846800KB job 00AF0020 633500KB realloc 2650100KB => failed realloc 1917000KB => failed max size = 1846800KB

예제 #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); return 0; } 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; } 10 20 30 40 50 60 70 80 ^Z average = 45

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

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

기본적인 연결 리스트 조작 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); 20 p2

예제: 책 리스트 #include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE 50 typedef struct NODE { char title[SIZE]; int year; struct NODE *link; } NODE; int main(void) { NODE *list = NULL, *prev, *p, *next; char buffer[SIZE]; while (1) { printf("책 제목: "); if (!gets(buffer)) break; p = (NODE*)malloc(sizeof(NODE)); strcpy(p->title, buffer); printf("책 출판 연도: "); gets(buffer); p->year = atoi(buffer);         if (list == NULL) list = p;         else prev->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);     return 0; }       책 제목: 컴퓨터 개론 책 출판 연도: 2006 책 제목: C 언어 책 출판 연도: 2007 책 제목: ^Z 컴퓨터 개론, 2006 C 언어, 2007

예제: 학생 리스트 list.h list.c #ifndef _LIST_H_ #define _LIST_H_ #define NAME_SIZE   20 typedef struct student_node {     int id;     char name[NAME_SIZE+1];     double gpa;     struct student_node *next; } SNODE; SNODE *make_list(void); void free_list(SNODE *p); void out_list(const SNODE *p); // double get_average(const SNODE *p); #endif #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; } void free_list(SNODE *p) {     SNODE *q;     for (; p; p = q) { q = p->next; free(p); } } void out_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) { ... }

예제: 학생 리스트 (계속) #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);     return 0; } 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