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
함수 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
자기 참조 구조체자기 참조 구조체
구조체 정의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
시스템 정의 매크로시스템 정의 매크로
프로그램의 편의를 위하여 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