2008 kang s c 2nd edition 14 동적 메모리 할당과 고급 처리.ppt...

36
14 동적 메모리 할당과 고급 처리 14 동적 메모리 할당과 고급 처리 조선대학교 전자공학과 장순석 교수 1

Upload: others

Post on 12-Oct-2019

0 views

Category:

Documents


0 download

TRANSCRIPT

14 동적 메모리 할당과 고급 처리14 동적 메모리 할당과 고급 처리

조선대학교 전자공학과 장순석 교수

1

C로 배우는 프로그래밍 기초 2nd Edition

동적 할당동적 할당

예측의 비효율

일반 변수의 선언과 사용은 변수를 정적(static)으로 사용 일반 변수의 선언과 사용은 변수를 정적(static)으로 사용

• 즉 정적인 방식이란 프로그램이 실행되기 이전에 이미 변수의 저장 공간을할당하고 그 모듈이나 또는 프로그램이 종료되면 변수가 해지되는 방식

int a 10;

메모리 사용 예측이 부정확한 경우는 충분한 메모리를 미리 확보해야하는 비효율

int a = 10;

하는 비효율

동적(dynamic) 메모리 할당(Memory Allocation) 동적인 메모리 할당을 위해서는 함수 malloc()을 이용, 메모리

공간을 확보

함수 malloc()은 stdlib.h 헤더 파일에 다음 함수 원형으로 정의

한국대학교 객체지향연구소2

C로 배우는 프로그래밍 기초 2nd Edition

함수 malloc()함수 malloc() 정수형 int의 메모리 공간을 함수 malloc()을 이용하여 동적으로

할당하는 소스• 함수 malloc()은 인자로 메모리 할당의 크기를 지정하고, 반환 값으로 할당된

메모리의 시작 주소를 반환

• 반환 값의 유형은 모든 자료형의 포인터로 이용할 수 있는 void * 확보된 공간의 주소는 int *의 변수에 저장하여 간접연산자 *pi를 확보된 공간의 주소는 int *의 변수에 저장하여 간접연산자 *pi를이용하여 원하는 값을 저장

한국대학교 객체지향연구소3

C로 배우는 프로그래밍 기초 2nd Edition

메모리 해제메모리 해제

함수 malloc()에 의하여 동적으로 할당된 메모리 공간은 더 이상 필요가없거나, 프로그램을 종료하는 경우에 반드시 메모리를 해제

• 함수 free()는 stdlib.h 헤더 파일에 다음 함수 원형으로 정의

함수 ll ()의 반환 소를 저장한 변수 i를 해제하려면 다음과 같이

void free(void *)

함수 malloc()의 반환 주소를 저장한 변수 pi를 해제하려면 다음과 같이기술

free(pi);

함수 free()는 인자로 해제할 메모리 공간의 주소 값을 갖는 포인터를이용하여 호출

함수 free(pi)가 호출되어 성공적으로 메모리가 해제되면 변수 pi는

(p )

함수 free(pi)가 호출되어 성공적으로 메모리가 해제되면 변수 pi는NULL 값을 가지며 더 이상 4바이트의 공간은 사용 불가능

한국대학교 객체지향연구소4

C로 배우는 프로그래밍 기초 2nd Edition

배열과 같은 메모리 할당배열과 같은 메모리 할당

여러 개 확보 자료형 int 배열과 같이 int 형 메모리 공간을 한 번에 여러 개자 형 t 배열과 같이 t 형 메 리 공간을 한 번에 여러 개

동적으로 확보• 함수 malloc()이 반환하는 값은 포인터인 int *의 변수로 저장하고,• 인자는 sizeof(int) * (확보하려는 배열의 원소의 개수)로 지정• 메모리 공간이 성공적으로 확보되면 변수 ary를 이용하여 다음과 같이• 메모리 공간이 성공적으로 확보되면 변수 ary를 이용하여 다음과 같이

배열을 이용

확보하여 이용하던 배열도 사용할 필요가 없으면 함수 free()를이용 해제이용, 해제

프로그램 실행 중에 동적으로 확보된 메모리는 프로그램이 종료되기

free(ary);

한국대학교 객체지향연구소5

프로그램 실행 중에 동적으로 확보된 메모리는 프로그램이 종료되기전에 반드시 해제

C로 배우는 프로그래밍 기초 2nd Edition

예제 14-1예제 14 1

한국대학교 객체지향연구소6

C로 배우는 프로그래밍 기초 2nd Edition

함수 calloc()함수 calloc() 초기 값을 0으로 저장

함수 calloc()은 메모리 공간을 확보하면서함수 calloc()은 메모리 공간을 확보하면서

• 함수 malloc()은 메모리 공간을 확보하고 그 장소에 초기 값을 저장하지 않음

• 함수 calloc()은 함수 원형이 stdlib.h 헤더 파일에 정의

인자 인자• 함수 calloc()에서 앞의 인자는 배열의 개수, 뒤의 인자는 한 원소의 크기

변수 ary는 int형 원소 3개를 확보한 저장공간을 기본 값 0으로 저장

한국대학교 객체지향연구소7

C로 배우는 프로그래밍 기초 2nd Edition

함수 realloc() 함수 realloc() 함수 realloc()은 이미 확보한 저장공간을 새로운 크기로 변경

void * realloc(void *, size_t);

인자첫 번째 인자는 변경할 저장공간의 주소이며 두 번째 인자는 변경하고 싶은 저장공간의 크기

( , _ );

int *reary, *cary;cary = (int *) calloc( 3, sizeof(int) );

첫 번째 인자는 변경할 저장공간의 주소이며, 두 번째 인자는 변경하고 싶은 저장공간의 크기 첫 번째 인자가 NULL이면 함수 malloc()과 같은 기능을 수행, 즉 지정된 크기만큼의 새로운

공간을 할당

한국대학교 객체지향연구소8

C로 배우는 프로그래밍 기초 2nd Edition

메모리 할당과 회수메모리 할당과 회수

정리

한국대학교 객체지향연구소9

C로 배우는 프로그래밍 기초 2nd Edition

예제 14-3예제 14 3

한국대학교 객체지향연구소10

C로 배우는 프로그래밍 기초 2nd Edition

자기 참조 구조체자기 참조 구조체

구조체 정의struct selfref {{

int n;struct selfref *next;//struct selfref next; //오류발생

구조체 selfref는 멤버로 int 형 n과 struct selfref* 형 next

};

구 체 selfref는 멤버 int 형 n과 struct selfref 형 next

• 멤버 next의 자료형을 잘 살펴보면 바로 정의하고 있는 구조체의 포인터 형

자기참조 구조체

자기 참조 구조체란 구조체의 멤버변수 중의 하나가 자기 자신의 자기 참조 구조체란 구조체의 멤버변수 중의 하나가 자기 자신의구조체 포인터 변수를 갖는 특수한 중첩된 구조체

멤버 next의 자료형을 포인터가 아닌 struct selfref로 한다면 컴파일시간에 에러 발생시간에 에러 발생

• 구조체 정의 구문에서 아래와 같이 자기 자신 구조체 유형 멤버는 허용하지않음

한국대학교 객체지향연구소11

C로 배우는 프로그래밍 기초 2nd Edition

리스트리스트

리스트(Linked List)

자기 참조 구조체는 반드시 구조체의 멤버 변수 중의 하나가 자기자신의 구조체 포인터 변수이어야 함

자기 참조 구조체는 동일 구조체의 표현을 여러 개 만들어 연결할 수있는 기능이 가능

이러한 구조를 연결 리스트(Linked List)라 함

간단히 두 개의 구조체를 연결하는 방법

우선 구조체 struct selfref를 하나의 자료형인 list 형으로 정의

자료형 list 포인터 형인 first와 second를 선언

typedef struct selfref list;

자료형 list 포인터 형인 first와 second를 선언

한국대학교 객체지향연구소12

C로 배우는 프로그래밍 기초 2nd Edition

연결 리스트 만들기연결 리스트 만들기

두 구조체 포인터 변수에 함수 malloc()을 이용하여 구조체의 멤버를저장할 수 있는 저장공간을 할당

first = (list *) malloc( sizeof(list) );second = (list *) malloc( sizeof(list) );

두 구조체에 first, second에 각각 정수 100, 200을 저장하고, 구조체second의 멤버 next에는 NULL을 저장• 구조체 first의 멤버 next에는 아직 아무 값도 저장하지 않은 상태

한국대학교 객체지향연구소13

C로 배우는 프로그래밍 기초 2nd Edition

연결 리스트의 노드 생성연결 리스트의 노드 생성

위 그림으로는 아직 구조체 first와 second는 아무 관련이 없음 만일 구조체 first가 다음 second 구조체를 가리킨다는 의미의 코딩을

원한다면 다음 문장이 필요원한다면 다음 문장이 필요

즉 구조체 first의 멤버 next에 구조체 second의 주소 값을 저장

first->next = second;

즉 구조체 first의 멤버 next에 구조체 second의 주소 값을 저장 이러한 자기 참조 구조체의 표현은 프로그램에서 자주 이용되는

자료구조로 프로그램에서는 매우 중요한 구조

한국대학교 객체지향연구소14

C로 배우는 프로그래밍 기초 2nd Edition

연결 리스트연결 리스트

프로그램 언어 C, C++, Java를 개발된 순서로 나열해보자. 이러한표현에서 가장 많이 이용하는 방법 중의 하나가 다음과 같은 표 형태표현에서 가장 많이 이용하는 방법 중의 하나가 다음과 같은 표 형태

이러한 순차적(sequential) 자료에 가장 적합한 메모리의 구조• 위와 같이 순차적 자료 항목을 표현하는 가장 쉬운 방법은 배열

자기 참조 구조체를 이용한 연결 리스트(Linked List) 구조도 순차적• 자기 참조 구조체를 이용한 연결 리스트(Linked List) 구조도 순차적자료에 적합

위 그림이 위 자료를 연결 리스트로 표현한 그림• 각각의 사각형은 한 항목의 자료를 표현하는 것으로 노드(node) 각각의 사각형은 한 항목의 자료를 표현하는 것으로 노드(node),

항목(item) 또는 원소(element)라 부름

• 헤드(head) 포인터는 연결 리스트의 처음 노드를 가리키는 포인터

연결 리스트의 가장 큰 장점

한국대학교 객체지향연구소15

• 연결 리스트 항목의 수를 프로그램 내부에서 메모리가 허용하는 한 늘릴 수있다는 것

C로 배우는 프로그래밍 기초 2nd Edition

노드 구조체노드 구조체

연결 리스트를 구현하려면 자기 참조 구조체를 이용

• 연결 리스트의 헤드 포인터는 연결 리스트의 첫 번째 원소를 가리키며, 각각의연결 리 의 헤 인터는 연결 리 의 첫 번째 원 를 가리키며, 각각의원소는 자기 다음의 원소를 가리킴

• 연결 리스트의 마지막 원소는 NULL 값을 가지고 있어 마지막 원소임을 알 수있음

위의 자료를 표현하는 구조체 struct linked_list를 정의

구조체 struct linked_list의 멤버로는

• 문자열을 저장할 char * 변수인 name, 문자열을 저장할 char 변수인 name, • 그리고 다른 구조체를 가리킬 포인터 next로 구성

문장 typedef를 이용하여 struct linked_list를 간단히 NODE로정의하고 이 NODE의 포인터를 LINK로 정의정의하고, 이 NODE의 포인터를 LINK로 정의

struct linked_list {char *name;struct linked list *next;struct linked_list *next;

};

typedef struct linked_list NODE;typedef NODE * LINK ;

한국대학교 객체지향연구소16

typedef NODE * LINK ;

C로 배우는 프로그래밍 기초 2nd Edition

구조체 노드 생성구조체 노드 생성

구조체 NODE에 “Java” 문자열을 저장하는 모듈• 우선 새로 생성할 노드의 주소를 저장할 변수 cur를 선언

LINK cur;char str[] = “Java”;

(NODE *) ll ( i f(NODE))

변수 cur가 가리키는 구조체의 멤버 name은 문자 포인터• 이 cur->name에 저장할 문자의 수만큼 메모리를 할당

cur = (NODE *) malloc(sizeof(NODE));

함수 strcpy()를 이용• 하여 “Java”가 저장된 문자열 str을 cur->name에 복사

cur->name = (char *) malloc(sizeof(char)*(strlen(str)+1));

• 하여 Java 가 저장된 문자열 str을 cur->name에 복사

현재 생성된 노드의 멤버 cur->next에는 초기에 NULL을 입력한 후,

strcpy(cur->name, str);

,필요하면 나중에 다른 구조체를 가리키도록 대입

cur ->next = NULL;

한국대학교 객체지향연구소17

C로 배우는 프로그래밍 기초 2nd Edition

함수 append() 시작함수 append() 시작 노드 head가 가리키는 노드로 시작하는 연결 리스트에 구조체 포인터

cur를 추가하는 함수 append() pp ()• 함수 append()는 시작 노드를 가리키는 head와 추가될 노드인 cur를 인자로

• 함수 append()는 시작 노드를 반환하도록

LINK append(LINK head, LINK cur)

함수 append()는 인자인 cur 노드를 이전의 연결 리스트 마지막 노드에

LINK append(LINK head, LINK cur) {

…}

함수 append()는 인자인 cur 노드를 이전의 연결 리스트 마지막 노드에추가하는 함수

• 함수 append()를 이용하여 다음 점선의 연결 리스트에 문자열 “Java”를추가하는 과정추가하는 과정

한국대학교 객체지향연구소18

C로 배우는 프로그래밍 기초 2nd Edition

함수 append() 구현함수 append() 구현 함수 내부에서 연결 리스트의 마지막 노드를 찾아가는데 필요한 지역 변수

nextNode를 선언하고 초기 값으로 head를 저장

만일 현재 연결 리스트에 아무 노드가 없는 상태라면 무조건 새로 추가되는 노드가

LINK nextNode = head;

첫 번째 노드가 될 것임

• 그러므로 이러한 경우에는 head에 cur를 대입하고, head를 반환하면서 함수를 종료

한국대학교 객체지향연구소19

C로 배우는 프로그래밍 기초 2nd Edition

마지막 노드 찾기마지막 노드 찾기

While 문 이용 만일기존의연결리스트에여러노드가있다면마지막노드를찾아가야함.만일기존의연결리스트에여러노드가있다면마지막노드를찾아가야함. while() 모듈을이용하면 nextNode는멤버 next의값이 NULL인마지막노드에이르게됨

while (nextNode->next != NULL) {

nextNode = nextNode->next;}}

한국대학교 객체지향연구소20

C로 배우는 프로그래밍 기초 2nd Edition

마지막 노드로 연결마지막 노드로 연결

이제 마지막 노드에 새로운 노드 “Java”를 연결하는 일 nextNode를이용하여 nextNode >next에 cur를대입 nextNode를이용하여 nextNode->next에 cur를대입

한국대학교 객체지향연구소21

C로 배우는 프로그래밍 기초 2nd Edition

연결 리스트 구현연결 리스트 구현

파일

한국대학교 객체지향연구소22

C로 배우는 프로그래밍 기초 2nd Edition

예제 14-5(1)예제 14 5(1)

한국대학교 객체지향연구소23

C로 배우는 프로그래밍 기초 2nd Edition

예제 14-5(2)예제 14 5(2)

한국대학교 객체지향연구소24

C로 배우는 프로그래밍 기초 2nd Edition

시스템 정의 매크로시스템 정의 매크로

프로그램의 편의를 위하여 C 언어에서는 다음과 같이 시스템에서이미 정의되어 있는 매크로를 제공이미 정의되어 있는 매크로를 제공

매크로는 프로그램 디버깅에 이용 가능

한국대학교 객체지향연구소25

C로 배우는 프로그래밍 기초 2nd Edition

#if와 #elif #if와 #elif C 언어의 조건문과 같은 전처리기 지시자 #if와 #elif를 제공

#if 다음에는 괄호가 없이 상수 수식이 오며 #if 다음에는 괄호가 없이 상수 수식이 오며,• 관계연산자나 논리연산자를 이용 가능

#if는 다음 수식의 결과가 0이 아니면 참으로 인식

건식이 참이면 가 나올 때까지 사이의 장을 실행

#if SYSTEM == WINDOWS #include "stdio.h"#endif

#if는 조건식이 참이면 #endif가 나올 때까지 사이의 문장을 실행

• #if는 다음과 같이 #elif와 #else도 제공

#if SYSTEM == WINDOWS #if SYSTEM WINDOWS #include "stdio.h"#elif SYSTEM == MAC#include "vax.h"#elif SYSTEM == UNIXe S S U#include "unix.h"#else #include "etc.h"#endif

한국대학교 객체지향연구소26

C로 배우는 프로그래밍 기초 2nd Edition

전처리기 결과 알기전처리기 결과 알기

비쥬얼 C++ 개발도구는 명령어 컴파일러 cl.exe를 제공

전처리기가 처리한 결과 소스를 보기 위해서는 다음과 같이 도스 전처리기가 처리한 결과 소스를 보기 위해서는 다음과 같이 도스명령어에서 –E 옵션을 사용

컴파일 명령어 cl에 옵션 –E를 입력하고 두 개의 파일을 입력하는방식.

cl –E 원본소스파일이름 >> 결과파일이름

위 명령을 성공적으로 수행하면 첫 번째 원본 소스 파일에서전처리한 결과의 소스가 두 번째 결과 파일 이름으로 생성

결과 파일이름을 편집기 열면 전처리기가 처리한 결과 소스를 볼 결과 파일이름을 편집기로 열면 전처리기가 처리한 결과 소스를 볼수 있음

cl –E 원본소스파일이름

한국대학교 객체지향연구소27

C로 배우는 프로그래밍 기초 2nd Edition

전처리기에서 디버그 이용전처리기에서 디버그 이용

#define DEBUG과 같이 기호상수를 정의하는 문장은 소스에기술하지 않고, 컴파일 명령어에서 옵션 –D를 이용하여 추가,가능

• 다음과 같이 컴파일 명령어 cl에 옵션 –D를 입력하고 계속해서기호상수를 입력

cl –D기호상수=값 소스파일이름

만일 #define DEBUG를 추가하는 컴파일 명령은

cl DDEBUG 소스파일이름cl –DDEBUG 소스파일이름

또한 #define LIMIT 100을 추가하는 컴파일 명령은

cl –DLIMIT=100 소스파일이름

한국대학교 객체지향연구소28

C로 배우는 프로그래밍 기초 2nd Edition

#ifdef#ifdef #ifdef는 다음에 나오는 기호상수가 정의되어 있으면

• #endif까지의 문장을 실행하고 그렇지 않으면 소스에서 제거• #endif까지의 문장을 실행하고, 그렇지 않으면 소스에서 제거

• #ifdef는 반드시 #endif로 종료해야

#define DEBUG…

#ifdef DEBUGif (i%5 == 0)

위 문장은 기호상수 DEBUG가 정의되어 있으므로 #ifdef 내부의 if

printf("DEBUG : 1부터 %d까지의 곱은 %d입니다.\n", i, prod);#endif

위 문장은 기호상수 DEBUG가 정의되어 있으므로 #ifdef 내부의 if 조건문을 포함하여 컴파일을 실행

만일 #define DEBUG 문장이 없다면

#ifd f 내부의 if 조건문은 소스에서 제거되므로 컴파일에 참여할 수 없고• #ifdef 내부의 if 조건문은 소스에서 제거되므로 컴파일에 참여할 수 없고,• 당연히 실행해도 그 부분은 실행되지 않음

한국대학교 객체지향연구소29

C로 배우는 프로그래밍 기초 2nd Edition

#ifndef와 defined#ifndef와 defined defined

#ifdef와 비슷한 구문으로 defined라는 전처리기 연산자를 이용 가능#ifdef와 비슷한 구문 defined라는 전처리기 연산자를 이용 가능

#if 문과 defined 연산자를 이용한 #if defined (DEBUG)와 #endif 문장• #ifdef DEBUG와 #endif 문장과 동일한 기능을 수행

• defined 다음의 괄호는 생략 가능

//#ifdef DEBUG#if defined (DEBUG)

if (i%5 == 0)

#ifndef #ifndef는 #ifdef와 반대

printf("DEBUG : 1부터 %d까지의 곱은 %d입니다.\n", i, prod);#endif

#ifndef는 #ifdef와 반대• 기호상수가 정의되어 있지 않으면 #endif까지의 문장을 전처리기에서 실행하고,

기호상수가 정의되어 있으면 전처리기에서 실행하지 않고 소스에서 제거

• #ifndef도 반드시 #endif로 종료#ifndef도 반드시 #endif로 종료

#ifndef LIMIT#define LIMIT 20#endif

한국대학교 객체지향연구소30

C로 배우는 프로그래밍 기초 2nd Edition

매크로 연산자 #매크로 연산자 # 매크로 연산자 #은 매크로 정의 시에 형식 인자를 문자열로 만드는 연산자

• 매크로에서 인자의 앞 뒤에 인용 부호 “를 넣어 문자열로 만들어 줌

• 다음 소스에서 매크로 PRT(D) 정의에서 인자 D의 사용을 #D로 하는 경우, 이 매크로 호출시에 인자의 앞 뒤에 인용 부호 “를 넣어 문자열로

#define PRT(D) printf(#D" = %2d 일때, ", D);

위 매크로 정의에서 PRT(i)의 호출은 다음 문장을 의미

( ) p ( )…

PRT(i)

위 매 정의에서 PRT(i)의 출은 다음 문장을 의미

C 언어에서 문자열 “i”와 ” = %2d 일때,”의 나열은 그대로 문자열의 연결을 의미

한국대학교 객체지향연구소31

• 즉 두 문자열이 연결된 문자열 “i = %2d 일때,”이 함수 printf()의 첫 인자

C로 배우는 프로그래밍 기초 2nd Edition

매크로 연산자 #매크로 연산자 # 다음과 같은 매크로 APRT()에서 APRT(fact[i])의 호출은 무슨

문장이 실행될까?문장이 실행될까?#define APRT(A) printf(#A" = %d\t", A);…

APRT(facto[i])

• 위 결과는 다음 문장으로 대체

APRT(facto[i])

한국대학교 객체지향연구소32

C로 배우는 프로그래밍 기초 2nd Edition

매크로 연산자 ##매크로 연산자 ## 연결(concatenation) 기능

매크로 연산자 ##은 양변의 토큰을 연결(concatenation)하는매크로 연산자 ##은 양변의 토큰을 연결(concatenation)하는기능을 수행

다음 매크로 AIPRT()에서 연산자 ##은 A과 [I]을 연결

매크로 호출 AIPRT(f t i)는 다음 문장을 표현

#define AIPRT(A, I) printf(#A"[%d] = %d\n", I, A##[I]);…

AIPRT(facto, i)

매크로 호출 AIPRT(facto, i)는 다음 문장을 표현

한국대학교 객체지향연구소33

C로 배우는 프로그래밍 기초 2nd Edition

#undef #undef #undef

#undef는 이미 정의된 기호 상수를 해지하는 지시자 #undef는 이미 정의된 기호 상수를 해지하는 지시자

#define LIMIT 20#undef LIMIT

위 구문은 20으로 정의된 기호상수 LIMIT를 전처리기 지시자# d f LIMIT로 그 효력을 상실#undef LIMIT로 그 효력을 상실

한국대학교 객체지향연구소34

C로 배우는 프로그래밍 기초 2nd Edition

예제 14-8예제 14 8

한국대학교 객체지향연구소35

C로 배우는 프로그래밍 기초 2nd Edition

36