쉽게 풀어쓴 c 언어 express
DESCRIPTION
쉽게 풀어쓴 C 언어 Express. 제 17 장 동적 메모리와 연결 리스트. C Express. 이번 장에서 학습할 내용. 동적 메모리 할당에 대한 개념을 이해하고 응용으로 연결 리스트를 학습합니다. 동적 메모리 연결 리스트. 메모리 할당 방법. 정적 (static) 생존 시간 (lifetime): 프로그램 시작 프로그램 끝 실행 중에는 메모리가 일정하게 유지되므로 별도의 관리가 불필요함 자동 (automatic) 생존 시간 : 해당 블록 실행 시작 블록 끝 - PowerPoint PPT PresentationTRANSCRIPT
© 2012 생능출판사 All rights reserved
쉽게 풀어쓴 C 언어 Express쉽게 풀어쓴 C 언어 Express
C Express제 17 장 동적 메모리와 연결 리스트
© 2012 생능출판사 All rights reserved
이번 장에서 학습할 내용
• 동적 메모리• 연결 리스트
동적 메모리 할당에 대한 개념을
이해하고 응용으로 연결 리스트를 학습합니다 .
© 2012 생능출판사 All rights reserved
메모리 할당 방법· 정적 (static)
· 생존 시간 (lifetime): 프로그램 시작 프로그램 끝· 실행 중에는 메모리가 일정하게 유지되므로 별도의 관리가 불필요함
· 자동 (automatic)· 생존 시간 : 해당 블록 실행 시작 블록 끝· 메모리 할당 및 해제 ( 반납 ) 가 블록과 연동되어 자동으로 이루어짐· 실행 시간 스택 (runtime stack) 사용
· 동적 (dynamic)· 생존 시간 : 동적 메모리 할당 동적 메모리 해제· 프로그래머가 생존 시간 결정· 힙 (heap) 사용
· 정적 / 자동 메모리 할당의 단점· 메모리의 크기가 프로그램 시작 전에 결정되어 고정됨
· 예 : int a[100]; // 배열의 크기에 변수를 사용할 수 없음· 결정된 크기보다 더 큰 데이터를 처리할 수 없음· 결정된 크기보다 작은 데이터를 처리하면 메모리 낭비 유발
© 2012 생능출판사 All rights reserved
동적 메모리 할당· 사용자의 요구에 따라 실행 중에
메모리 할당 및 해제· 할당 사용 해제
· 필요한 만큼만 메모리 할당 가능 메모리를 효율적으로 사용
· 라이브러리 함수 사용 : <stdlib.h>· 할당 : malloc(), calloc()· 재할당 : realloc()· 해제 : free()
할당요구
#include <stdio.h>#include <stdlib.h>
int main(void){int *p;p = (int *)malloc( sizeof(int) );...
}
#include <stdio.h>#include <stdlib.h>
int main(void){int *p;p = (int *)malloc( sizeof(int) );...
}
프로그램
운영 체제
© 2012 생능출판사 All rights reserved
동적 메모리 할당 / 해제 함수
#include <stdlib.h>
int *p;
p = (int*)malloc(sizeof(int)); // 할당if (p == NULL) … // 에러 처리
*p = 123; // 사용
free(p); // 해제
void *malloc(size_t size);
· size 바이트만큼 동적 메모리 블록 할당· 반환 값 : 성공 동적 메모리 블록 시작 포인터 , 실패 NULL· 할당된 메모리 블록은 초기화되지 않음
void free(void *p);
· p 가 가리키는 동적 메모리 해제· p 가 NULL 포인터이면 무시
?p
malloc
123p
free
© 2012 생능출판사 All rights reserved
예제#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;
}
0123456789
© 2012 생능출판사 All rights reserved
예제#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
© 2012 생능출판사 All rights reserved
예제#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 Programming2: Data Structure
© 2012 생능출판사 All rights reserved
calloc()
p
??????
int *p = (int*)malloc(6 * sizeof(int));
p
int *p = (int*)calloc(6, sizeof(int)); 000000
void *calloc(size_t n, size_t size);
· 크기가 size 바이트인 항목 n 개를 저장할 수 있는 동적 메모리 할당· ‘size * n’ 바이트 메모리 할당· 반환 값 : 성공 동적 메모리 블록 시작 포인터 , 실패 NULL· 할당된 메모리 블록은 0 으로 초기화됨
// 다음은 모두 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));
© 2012 생능출판사 All rights reserved
예제#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
© 2012 생능출판사 All rights reserved
증가
realloc()void *realloc(void *p, size_t size);· p 가 가리키는 동적 메모리의 크기를 size 바이트로 변경
· 메모리 크기가 size 바이트로 증가 / 감소됨· 동적 메모리 블록이 다른 위치로 이동될 수 있음· p 가 가리키는 이전 메모리 내용은 변경되지 않음
· 크기가 감소되는 경우에는 감소된 부분만 이전 내용과 동일· 증가된 부분은 초기화되지 않음· 반환 값 : 성공 동적 메모리 블록 시작 포인터 , 실패 NULL
· 성공 반환되는 포인터는 p 와 다를 수 있음· 실패 p 가 가리키는 이전 메모리 내용은 변경되지 않음
· p 가 NULL 이면 malloc() 과 동일
q
int *q = (int*)realloc(p, 8 * sizeof(int)); 924751 ??
p
int *p = (int*)malloc(6 * sizeof(int)); 924751
q
int *q = (int*)realloc(p, 4 * sizeof(int)); 4751
감소
© 2012 생능출판사 All rights reserved
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;
© 2012 생능출판사 All rights reserved
예제#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 => succeededjob 006D0020 4200KBrealloc 1846800KB => succeededjob 00AF0020 1846800KBjob 00AF0020 633500KBrealloc 2650100KB => failedjob 00AF0020 1846800KBrealloc 1917000KB => failedjob 00AF0020 1846800KB
max size = 1846800KB
© 2012 생능출판사 All rights reserved
예제#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 4050 60 70 80^Zaverage = 45
© 2012 생능출판사 All rights reserved
메인 메모리
A
B
CD
E
연결 리스트· 배열 (array)
· 간단하고 다루기 쉬움· 특정 위치의 원소에 대한 접근이 빠름· 삽입 / 삭제가 비효율적
· 연결 리스트 (linked list)· 각 원소가 포인터를 사용하여 다음 원소를 가리킴· 다루기 어렵고 특정 위치의 원소에 대한 접근이 느림· 삽입 / 삭제가 용이함
0011
2233
4455
6677
8899
삽입
B
AC D
E
N
삭제
B
AC D
E
© 2012 생능출판사 All rights reserved
10 20 NULL30 NULL50 NULLNULL40plist
첫번째 노드를 가리키는 포인터를 헤드포인터라고 하고 맨 마지막 노드의 링크 필드
는 NULL입니다.
연결 리스트· 노드 (node) = 데이터 필드 (data field) + 링크 필드 (link field)
· 일반적으로 동적 메모리를 사용하여 생성
data link
연결 리스트의 노드는데이터 필드와 링크
필드로 이루어집니다.
· 자기 참조 구조체 (self-referential structure): 멤버 중에 자신과 같은 타입의 구조체를 가리키는 포인터가 있는 구조체
struct node {int data;struct node
*link;};
· 헤드 포인터 (head pointer): 첫 번째 노드를 가리키는 포인터
© 2012 생능출판사 All rights reserved
기본적인 연결 리스트 조작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);
10 NULLp1
10p1 20 NULL
10p1 20 NULL
10 NULLp1 20p2
© 2012 생능출판사 All rights reserved
예제 : 책 리스트#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
컴퓨터 개론 , 2006C 언어 , 2007
© 2012 생능출판사 All rights reserved
예제 : 학생 리스트#ifndef _LIST_H_#define _LIST_H_
#define NAME_SIZE 20typedef 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, &n-ode.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) { ... }
list.h list.c
© 2012 생능출판사 All rights reserved
예제 : 학생 리스트 ( 계속 )#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.1ID NAME GPA: 2013002 김유신 4.2ID NAME GPA: 2013003 이순신 4.3ID NAME GPA: ^Z
2013003 이순신 4.32013002 김유신 4.22013001 강감찬 4.1