쉽게 풀어쓴 c 언어 express

20
© 2012 생생생생생 All rights reserved 쉽쉽 쉽쉽쉽 C 쉽쉽 Express C Express 생 17 생 생생 생생생생 생생 생생생

Upload: yazid

Post on 06-Jan-2016

222 views

Category:

Documents


8 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

쉽게 풀어쓴 C 언어 Express쉽게 풀어쓴 C 언어 Express

C Express제 17 장 동적 메모리와 연결 리스트

Page 2: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이번 장에서 학습할 내용

• 동적 메모리• 연결 리스트

동적 메모리 할당에 대한 개념을

이해하고 응용으로 연결 리스트를 학습합니다 .

Page 3: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

메모리 할당 방법· 정적 (static)

· 생존 시간 (lifetime): 프로그램 시작 프로그램 끝· 실행 중에는 메모리가 일정하게 유지되므로 별도의 관리가 불필요함

· 자동 (automatic)· 생존 시간 : 해당 블록 실행 시작 블록 끝· 메모리 할당 및 해제 ( 반납 ) 가 블록과 연동되어 자동으로 이루어짐· 실행 시간 스택 (runtime stack) 사용

· 동적 (dynamic)· 생존 시간 : 동적 메모리 할당 동적 메모리 해제· 프로그래머가 생존 시간 결정· 힙 (heap) 사용

· 정적 / 자동 메모리 할당의 단점· 메모리의 크기가 프로그램 시작 전에 결정되어 고정됨

· 예 : int a[100]; // 배열의 크기에 변수를 사용할 수 없음· 결정된 크기보다 더 큰 데이터를 처리할 수 없음· 결정된 크기보다 작은 데이터를 처리하면 메모리 낭비 유발

Page 4: 쉽게 풀어쓴  C 언어  Express

© 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) );...

}

프로그램

운영 체제

Page 5: 쉽게 풀어쓴  C 언어  Express

© 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

Page 6: 쉽게 풀어쓴  C 언어  Express

© 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

Page 7: 쉽게 풀어쓴  C 언어  Express

© 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

Page 8: 쉽게 풀어쓴  C 언어  Express

© 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

Page 9: 쉽게 풀어쓴  C 언어  Express

© 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));

Page 10: 쉽게 풀어쓴  C 언어  Express

© 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

Page 11: 쉽게 풀어쓴  C 언어  Express

© 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

감소

Page 12: 쉽게 풀어쓴  C 언어  Express

© 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;

Page 13: 쉽게 풀어쓴  C 언어  Express

© 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

Page 14: 쉽게 풀어쓴  C 언어  Express

© 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

Page 15: 쉽게 풀어쓴  C 언어  Express

© 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

Page 16: 쉽게 풀어쓴  C 언어  Express

© 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): 첫 번째 노드를 가리키는 포인터

Page 17: 쉽게 풀어쓴  C 언어  Express

© 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

Page 18: 쉽게 풀어쓴  C 언어  Express

© 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

Page 19: 쉽게 풀어쓴  C 언어  Express

© 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

Page 20: 쉽게 풀어쓴  C 언어  Express

© 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