ABC 11장

Similar documents
ABC 10장

슬라이드 1

11장 포인터

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

OCW_C언어 기초

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

<4D F736F F F696E74202D20C1A63132B0AD20B5BFC0FB20B8DEB8F0B8AEC7D2B4E7>

untitled

금오공대 컴퓨터공학전공 강의자료

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft PowerPoint - chap10-함수의활용.pptx

ABC 9장

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

Microsoft PowerPoint - chap11-포인터의활용.pptx

untitled

<4D F736F F F696E74202D20C1A63137C0E520B5BFC0FBB8DEB8F0B8AEBFCD20BFACB0E1B8AEBDBAC6AE>

Microsoft PowerPoint - chap09.ppt

Microsoft PowerPoint - chap03-변수와데이터형.pptx

C 언어 프로그래밊 과제 풀이

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

K&R2 Reference Manual 번역본

Microsoft PowerPoint - chap12-고급기능.pptx

ABC 6장

본 강의에 들어가기 전

Microsoft PowerPoint - chap06-2pointer.ppt


ABC 11장

untitled

Lab 3. 실습문제 (Single linked list)_해답.hwp

11장 포인터

Chapter 4. LISTS

슬라이드 1

1장. 유닉스 시스템 프로그래밍 개요

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

기초컴퓨터프로그래밍

Lab 4. 실습문제 (Circular singly linked list)_해답.hwp

윤성우의 열혈 TCP/IP 소켓 프로그래밍

1 장 C 언어복습 표준입출력배열포인터배열과포인터함수 const와포인터구조체컴파일러사용방법 C++ 프로그래밍입문

Chapter 4. LISTS

03장.스택.key

Microsoft PowerPoint - chap04-연산자.pptx

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap05-제어문.pptx

Microsoft PowerPoint - chap06-5 [호환 모드]

Microsoft PowerPoint - ch07 - 포인터 pm0415

OCW_C언어 기초

PowerPoint 프레젠테이션

歯9장.PDF

PowerPoint 프레젠테이션


chap 5: Trees

쉽게 풀어쓴 C 프로그래밍

중간고사

PowerPoint 프레젠테이션

컴파일러

Microsoft PowerPoint - chap-11.pptx

Microsoft PowerPoint - additional01.ppt [호환 모드]

5.스택(강의자료).key

Microsoft PowerPoint - chap06-1Array.ppt

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

untitled

PowerPoint 프레젠테이션

제 14 장포인터활용 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

Microsoft PowerPoint - ch08 - 구조체 (structure) am0845

C 프로그래밊 개요

PowerPoint Template

0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4

Microsoft PowerPoint - Chapter_08.pptx

Microsoft PowerPoint - [2009] 02.pptx

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - 제11장 포인터(강의)

쉽게 풀어쓴 C 프로그래밍

PowerPoint Presentation

02장.배열과 클래스

슬라이드 1

OCW_C언어 기초

제 11 장포인터 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

<4D F736F F F696E74202D20C1A639C0E520C7D4BCF6BFCDBAAFBCF6>

chap01_time_complexity.key


C++ Programming

Microsoft PowerPoint - 제11장 포인터

Microsoft PowerPoint - 03_(C_Programming)_(Korean)_Pointers

KNK_C_05_Pointers_Arrays_structures_summary_v02

C언어 및 실습 C Language and Practice

쉽게 풀어쓴 C 프로그래밍

untitled

Chapter #01 Subject

PowerPoint 프레젠테이션

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

1. 표준입출력 C++ : C의모든라이브러리를포함 printf, scanf 함수사용가능예 : int, double, 문자열값을입력받고출력하기 #include <cstdio> int ivar; double dvar; char str[20]; printf("int, dou

PowerPoint 프레젠테이션

ABC 2장

03_queue

Microsoft PowerPoint - 08-C-App-19-Quick-Preprocessor

int main(void) int a; int b; a=3; b=a+5; printf("a : %d \n", a); printf("b : %d \n", b); a b 3 a a+5 b &a(12ff60) &b(12ff54) 3 a 8 b printf(" a : %x \

원형연결리스트에대한설명중틀린것은 모든노드들이연결되어있다 마지막에삽입하기가간단한다 헤더노드를가질수있다 최종노드포인터가 NULL이다 리스트의 번째요소를가장빠르게찾을수있는구현방법은무엇인가 배열 단순연결리스트 원형연결리스트 이중연결리스트 단순연결리스트의노드포인터 가마지막노드를

Transcription:

13 장고급프로그래밍 김명호

내용 C 시스템의메모리배치 대형프로그램의구성 정적외부변수와함수 추상자료형 가변인자함수 미리정의된매크로와가변인자매크로 자기참조구조체 라이브러리 신호 1

C 프로그램실행메모리 메모리배치 스택 상위메모리 힙 데이터 텍스트 하위메모리 2

C 프로그램실행메모리 메모리배치 스택 : 함수의지역변수, 매개변수, 리턴주소저장 힙 : malloc(), calloc() 에의해할당되는공간 텍스트 : 실행코드 ( 문장 ) 저장 데이터 : 전역변수, 정적변수저장 실행파일에는텍스트와초기화된전역변수와정적변수저장 초기화되지않은것에대해서는이름과크기만저장 (BSS, Block Started by Symbol) 3

프로그램 13.1 메모리배치 int same; // BSS 부분에저장 float gallon2liter = 3.7854118; // 데이터부분에저장 float g2l[n][2]; // BSS 부분에저장 int last = 1; // 데이터부분에저장 float compute(float); // main() 과 compute() 함수의모든문장은텍스트부분에저장 int main(void){ float liter, gallon; int i;... float compute(float input){ static int cnt = 0; // BSS 부분에저장 float result; int i;... 4

C 프로그램실행메모리 메모리배치 스택 Liter, Gallon i 상위메모리 힙 데이터 Same, g2l, cnt Gallon2liter, last main : 텍스트... compute :... 하위메모리 5

대형프로그램구성 프로그램은여러파일로작성될수있음 보통관련된함수들을하나의파일에저장함 한프로그램을이루는파일들은보통같은디렉터리에저장됨 6

프로그램 13.2 (main.c) #include <stdio.h> 대형프로그램구성 typedef struct grade{ int grade[3]; char p_f[3]; int sum; float avg; grade; int grade_proc3(grade *); int main(void){ grade st = {{0, {0, -1, -1.0; printf(" 성적입력 ( 국어, 산수, 과학 ) : "); scanf("%d%d%d", &st.grade[0], &st.grade[1], &st.grade[2]); if (grade_proc3(&st)) return 1; printf(" 국어 : %d (%c)\n", st.grade[0], st.p_f[0]); printf(" 산수 : %d (%c)\n", st.grade[1], st.p_f[1]); printf(" 과학 : %d (%c)\n", st.grade[2], st.p_f[2]); printf(" 총점 : %d\n", st.sum); printf(" 평균 : %.2f\n", st.avg); return 0; 7

대형프로그램구성 프로그램 13.2 (grade.c) #include <stdio.h> typedef struct grade{ int grade[3]; char p_f[3]; int sum; float avg; grade; int grade_proc3(grade * stp) { if (stp == NULL) { printf(" 오류 : NULL 포인터 \n"); return -1; stp -> sum = stp -> grade[0] + stp -> grade[1] + stp -> grade[2]; stp -> avg = stp -> sum / 3.0; stp -> p_f[0] = stp -> grade[0] < 60? 'f' : 'p'; stp -> p_f[1] = stp -> grade[1] < 60? 'f' : 'p'; stp -> p_f[2] = stp -> grade[2] < 60? 'f' : 'p'; return 0; 8

컴파일 대형프로그램구성 프로그램을이루는모든파일을명시하면됨 gcc -o grade main.c grade.c 파일별컴파일 gcc -c main.c gcc -c grade.c gcc -o grade main.o grade.o 수정된파일만컴파일하면됨 gcc -c main.c gcc -o grade main.o grade.o 9

사용자헤더파일 대형프로그램구성 프로그램을이루는파일들이공통으로사용하는헤더파일이나, 매크로, 함수원형, 구조체선언등을모아두는파일 확장자로 h 를사용함 다른소스파일과같은디렉터리에둠 대형프로그램을여러명이같이개발할때유용함 헤더파일을여러번포함해도되게끔작성하는것이좋음 10

프로그램 13.3 (grade.h) #include <stdio.h> typedef struct grade{ int grade[3]; char p_f[3]; int sum; float avg; grade; int grade_proc3(grade *); 대형프로그램구성 11

대형프로그램구성 프로그램 13.3 (main.c) #include "grade.h" int main(void) { grade st = {{0, {0, -1, -1.0; printf(" 성적입력 ( 국어, 산수, 과학 ) : "); scanf("%d%d%d", &st.grade[0], &st.grade[1], &st.grade[2]); if (grade_proc3(&st)) return 1; printf(" 국어 : %d (%c)\n", st.grade[0], st.p_f[0]); printf(" 산수 : %d (%c)\n", st.grade[1], st.p_f[1]); printf(" 과학 : %d (%c)\n", st.grade[2], st.p_f[2]); printf(" 총점 : %d\n", st.sum); printf(" 평균 : %.2f\n", st.avg); return 0; 12

대형프로그램구성 프로그램 13.3 (grade.c) #include "grade.h" int grade_proc3(grade * stp) { if (stp == NULL) { printf(" 오류 : NULL 포인터 \n"); return -1; stp -> sum = stp -> grade[0] + stp -> grade[1] + stp -> grade[2]; stp -> avg = stp -> sum / 3.0; stp -> p_f[0] = stp -> grade[0] < 60? 'f' : 'p'; stp -> p_f[1] = stp -> grade[1] < 60? 'f' : 'p'; stp -> p_f[2] = stp -> grade[2] < 60? 'f' : 'p'; return 0; 13

대형프로그램구성 프로그램 13.3 (grade.h) #ifndef _GRADE_H_ // 같은헤더파일이두번이상포함되는것을방지함 #define _GRADE_H_ #include <stdio.h> typedef struct grade{ int grade[3]; char p_f[3]; int sum; float avg; grade; void grade_proc3(grade *); #endif // _GRADE_H_ 14

함수밖에선언된변수 외부변수 모든함수에서참조가가능함 함수간에정보전달을위해유용함 다른파일에정의된외부변수는 extern 을사용하여참조할수있음 15

프로그램 13.4 (main.c) #include <stdio.h> 외부변수 int quotient, rem; // 전역변수선언 int divide(int, int); int main(void) { int a = 10, b = 3; extern int quotient, rem; // 전역변수참조선언, 생략할수있음 if (divide(a, b)) printf("0으로나눌수없습니다.\n"); else printf("%d / %d : 몫은 %d이고나머지는 %d입니다.\n", a, b, quotient, rem); return 0; 16

외부변수 프로그램 13.4 (divide.c) int is_zero(int); int divide(int dividend, int divisor) { extern int quotient, rem; // 전역변수참조선언 if (is_zero(divisor)) return -1; quotient = dividend / divisor; rem = dividend % divisor; return 0; int is_zero(int num) { if (num) return 0; return 1; 17

정적외부변수 외부변수에 static 이적용된변수 정적외부변수는그변수가선언된파일내에있는함수에서만사용될수있음 데이터접근을제한하여안전한프로그램을만들수있음 18

정적외부함수 함수정의에 static 이적용된함수 정적외부함수는그함수가정의된파일내에있는함수에서만사용될수있음 19

정적외부변수 프로그램 13.5 (password.c) #include <stdbool.h> static int passwd = 78; static bool is_login = false; static void set_login(bool ok){ is_login = ok; int access(int num){ if (num!= passwd) { set_login(false); return -1; set_login(true); return 0; int change_passwd(int new){ if (!is_login) return -1; passwd = new; return 0; // 정적외부변수, 다른파일에서사용못함 // 정적외부변수, 다른파일에서사용못함 // 정적외부함수, 다른파일에서호출못함 20

프로그램 13.5 (main.c) 정적외부변수 #include <stdio.h> int access(int); int change_passwd(int); int main(void){ int num, new, select = 1; while (select){ printf("0: 종료, 1: 로그인, 2: 패스워드변경 \n번호를선택하세요 :"); scanf("%d", &select); switch(select) {... case 1: printf(" 패스워드 : "); scanf("%d", &num); if (access(num)) printf(" 잘못된패스워드입니다.\n"); else printf(" 로그인됐습니다.\n"); break; 21

정적외부변수 프로그램 13.5 (main.c) case 2: printf(" 새로운패스워드 : "); scanf("%d", &new); if (change_passwd(new)) printf(" 패스워드를변경할수없습니다.\n"); else printf(" 패스워드가변경됐습니다.\n"); break; default: printf(" 잘못된번호입니다.\n"); return 0; 22

$ password 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :1 패스워드 : 78 로그인됐습니다. 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :2 새로운패스워드 : 90 패스워드가변경됐습니다. 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :0 프로그램을종료합니다. $ password 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :1 패스워드 : 90 잘못된패스워드입니다. 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :2 새로운패스워드 : 90 패스워드를변경할수없습니다. 0: 종료, 1: 로그인, 2: 패스워드변경번호를선택하세요 :0 프로그램을종료합니다. 프로그램결과 23

추상자료형 처리해야할데이터집합과그연산을정의한명세 데이터는추상자료형에서정의된연산자에의해서만다루어지기때문에데이터를보호할수있음 구현에대해서는고려하지않음 24

프로그램 13.1 #include <stdio.h> #define N 10 int same; float gallon2liter = 3.7854118; float g2l[n][2]; int last = 1; float compute(float); 25

프로그램 13.1 int main(void){ float liter, gallon; int i; while (last){ printf(" 겔론 : "); scanf("%f", &gallon); liter = compute(gallon); printf("%.2f 겔론은 %.2f 리터입니다.\n", gallon, liter); printf("%d 번변환했습니다.\n", N); for (i = 0; i < N; i++) printf("%.2f 겔론 : %.2f 리터 \n", g2l[i][0], g2l[i][1]); return 0; 26

프로그램 13.1 float compute(float input){ static int cnt = 0; float result; int i; for (i = 0; i < cnt; i++) if (g2l[i][0] == input) { same++; return g2l[i][1]; result = input * gallon2liter; g2l[cnt][0] = input; g2l[cnt][1] = result; cnt++; if (cnt == N) last = 0; return result; 27

프로그램 13.1 int main(void){ float liter, gallon; int i; while (last){... liter = compute(gallon);...... float compute(float input){ static int cnt = 0; float result; int i;... 28

메모리스택 함수호출에의해생성되는함수프레임은메모리의스택부분에저장됨 함수프레임 : 지역변수, 매개변수, 리턴주소로구성됨 저장된함수프레임은함수가종료되면삭제됨 가장나중에호출된함수가가장빨리종료되기때문에메모리스택에서가장먼저삭제되는것은가장최근에쌓인함수프레임임 ( 후입선출 ) 29

추상자료형 함수호출예 ( 프로그램 13.1) main() 함수호출 return address liter gallon i main() 프레임 30

추상자료형 함수호출예 ( 프로그램 13.1) compute() 함수호출 return address liter gallon i input return address result i main() 프레임 compute() 프레임 31

추상자료형 함수호출예 ( 프로그램 13.1) compute() 함수 return return address liter gallon i main() 프레임 32

추상자료형 추상자료형스택 (stack) 데이터를선형으로저장하는자료구조로나중에저장한것을먼저사용함 ( 후입선출 ) 삽입 삭제 33

추상자료형 처리해야할데이터집합과그연산을정의한명세 데이터는추상자료형에서정의된연산자에의해서만다루어지기때문에데이터를보호할수있음 구현에대해서는고려하지않음 34

추상자료형 추상자료형스택 (stack) 연산자 push : 스택에데이터삽입 pop : 스택으로부터데이터삭제 top : 스택의톱에있는데이터를삭제하지않고확인 empty : 스택이비어있는지검사 full : 스택이꽉찼는지검사 reset : 스택초기화 35

추상자료형스택구현 데이터를선형으로저장하는방법 배열 링크드리스트 문자를저장하는스택을배열로구현 #define MAX 100 typedef struct stack { char s[max]; int top; stack; 36

스택연산자구현예 push 연산자 추상자료형스택구현 함수 13.1 void push(char c, stack *stk) { stk -> top++; stk -> s[stk -> top] = c; 37

추상자료형스택구현 프로그램 13.6 (stack.h) #include <stdio.h> #include <stdbool.h> #define MAX_LEN 100 #define EMPTY -1 #define FULL (MAX_LEN - 1) typedef struct stack { char s[max_len]; int top; stack; void reset(stack *stk); void push(char c, stack *stk); char pop(stack *stk); char top(const stack *stk); bool empty(const stack *stk); bool full(const stack *stk); 38

추상자료형스택구현 프로그램 13.6 (stack.c) #include "stack.h" void reset(stack *stk){ stk -> top = EMPTY; void push(char c, stack *stk){ stk -> top++; stk -> s[stk -> top] = c; char pop(stack *stk){ return (stk -> s[stk -> top--]); char top(const stack *stk){ return (stk -> s[stk -> top]); bool empty(const stack *stk){ return (stk -> top == EMPTY); bool full(const stack *stk){ return (stk -> top == FULL); 39

추상자료형스택구현 프로그램 13.6 (main.c) #include "stack.h" int main(void){ char str[] = "Stack Test!"; int i; stack s; reset(&s); // 스택초기화 printf(" 문자열 : %s\n", str); // 스택에문자열 push for (i = 0; str[i]!= '\0'; ++i) if (!full(&s)) push(str[i], &s); printf(" 역문자열 : "); // 스택에서문자열 pop while (!empty(&s)) putchar(pop(&s)); putchar('\n'); return 0; 40

프로그램결과 문자열 : Stack Test! 역문자열 :!tset kcats 41

가변인자함수 함수의매개변수개수가정해져있지않는함수 매개변수에서 ( 점세개 ) 으로표시 printf() printf(" 재미있는 C!\n"); printf(" 이름 : %s.", " 김진혁 "); printf("%d * %d = %d\n", 123, 43, 123 * 43); 함수원형 int printf(const char *cntrl_string,...); 42

가변인자함수 스택 printf("%d * %d = %d\n", 123, 43, 123 * 43); printf() 호출... 0x38454646 123 43 5289 return address...... 43

가변인자함수 스택 printf("%d * %d = %d\n", 123, 43, 123 * 43); printf() 호출... 0x38454646 char * 4 byte 123 int 4 byte 43 int 4 byte 5289 int 4 byte return address...... 44

가변인자함수 <stdarg.h> 에정의된매크로를사용하여만듦 매크로 va_start(ap, v) va_arg(ap, type) 설명 ap가가변인자의첫번째인자를포인트하게한다. v는가변인자바로직전의인자이다. ap가포인트하는곳의값을 type 형으로읽고, ap는다음인자를포인트하게한다. va_copy(dest, src) src 포인터를 dest 로복사한다. C99 에서추가되었다. va_end(ap) va_start() 로초기화된 ap 포인터를제거한다. va_start() 를사용한함수에서사용해야한다. 45

가변인자함수 스택 printf("%d * %d = %d\n", 123, 43, 123 * 43); printf() 호출 va_start(ap, v)... 0x38454646 char * 4 byte 123 int 4 byte 43 int 4 byte 5289 int 4 byte return address...... 46

가변인자함수 스택 printf("%d * %d = %d\n", 123, 43, 123 * 43); printf() 호출 va_arg(ap, int)... 0x38454646 char * 4 byte 123 int 4 byte 43 int 4 byte 5289 int 4 byte return address...... 47

가변인자함수 스택 printf("%d * %d = %d\n", 123, 43, 123 * 43); printf() 호출 va_arg(ap, int)... 0x38454646 char * 4 byte 123 int 4 byte 43 int 4 byte 5289 int 4 byte return address...... 48

가변인자함수 프로그램 13.7 #include <stdio.h> #include <stdarg.h> #define END 0 #define INT 1 #define DOUBLE 2 double va_sum(int,...); int main(void) { printf("sum = %.3f\n", va_sum(int, 3, DOUBLE, 3.0, END)); printf("sum = %.3f\n", va_sum(double, 20.0, INT, 90, DOUBLE, 0.5, END)); return 0 ; 49

가변인자함수 프로그램 13.7 double va_sum(int type,...) { double sum = 0.0; va_list ap; va_start(ap, type); while(type!= 0){ if (type == INT) sum += va_arg(ap, int); else sum += va_arg(ap, double); type = va_arg(ap, int); va_end(ap); return sum; 50

프로그램결과 Sum = 6.000 Sum = 110.500 51

미리정의된매크로 7 개의미리정의된매크로가있음 매크로 DATE FILE LINE 미리정의된식별자 (C99) func : 현재수행중인함수이름을갖는문자배열 값 현재날짜를포함하는문자열 파일이름을포함하는문자열 현재라인번호를나타내는정수 STDC 표준을따르는경우 1, 아니면 0 TIME 현재시간을포함하는문자열 STDC_HOSTED 호스트구현이면 1, 아니면 0 STDC_VERSION 정수상수 199901L 52

가변인자매크로 C99부터매크로도가변인자를가질수있음 가변인자를점세개 ( ) 로표시 매크로정의에서가변매개변수는 VA_ARGS 로명시 예제 #define ERRPRINTF(...) \ printf(" 오류 : (" FILE " 파일 ) " VA_ARGS ) 53

가변인자매크로 프로그램 13.8 #include <stdio.h> #define ERRPRINTF(...) printf(" 오류 : (" FILE " 파일 ) " VA_ARGS ) int main(void){ float divisor, dividend; printf("******** 나누기프로그램 ********\n"); printf(" 피제수를입력하세요 : "); scanf("%f", &dividend); printf(" 제수를입력하세요 : "); scanf("%f", &divisor); if (divisor == 0.0) ERRPRINTF(" 제수가 %.3f 입니다.\n", divisor); else printf("%.3f / %.3f = %.3f\n", dividend, divisor, dividend / divisor); return 0; 54

프로그램결과 ******** 나누기프로그램 ******** 피제수를입력하세요 : 89 제수를입력하세요 : 0 오류 : (divide.c 파일 ) 제수가 0 입니다. 55

컴파일러메시지형태 가변인자매크로 divide.c: In function `main': divide.c:14: error: 'divisor' undeclared (first use in this function) 오류가있는파일명, 함수명, 행번호표시 가변인자매크로로만든오류출력매크로 #define ERRPRINTF2(...) \ printf( FILE ": '%s' 함수 :\n", func ),\ printf( FILE ":%d: 오류 :", LINE ),\ printf( VA_ARGS ) 여러문장을사용하기위해콤마연산자사용 56

가변인자매크로 매크로정의에서콤마연산자대신문장의끝을나타내는세미콜론 (;) 을사용하면문제가발생함 #define ERRPRINTF2(...) \ printf( FILE ": '%s' 함수 :\n", func );\ printf( FILE ":%d: 오류 :", LINE );\ printf( VA_ARGS ) ERRPRINTF2(" 제수가 0 입니다.\n"); printf("divide.c" ": '%s' 함수 :\n", func ); printf("divide.c" ":%d: 오류 :", 17); printf(" 제수가 0입니다.\n", divisor); 57

문제발생예제 가변인자매크로 if (divisor == 0.0) ERRPRINTF2(" 제수가 0 입니다.\n"); else printf("%.3f / %.3f = %.3f\n", dividend, divisor, dividend / divisor); if (divisor == 0.0) printf("divide.c" ": '%s' 함수 :\n", func ); printf("divide.c" ":%d: 오류 :", 17); printf(" 제수가 0입니다.\n", divisor); else printf("%.3f / %.3f = %.3f\n", dividend, divisor, dividend / divisor); 58

가변인자매크로 매크로가여러문장으로정의될때에는 do-while 구문을사용하는것이좋음 #define ERRPRINTF2(...) \ do {\ printf( FILE ": '%s' 함수 :\n", func );\ printf( FILE ":%d: 오류 :", LINE );\ printf( VA_ARGS ); \ while (0) while 의조건으로 0 을사용해야함, 0 이외의값을사용하면무한루프에빠짐 59

가변인자매크로 do-while 문은한문장으로취급되기때문에오류가발생하지않음 if (divisor == 0.0) else do { printf("divide.c" ": '%s' 함수 :\n", func ); printf("divide.c" ":%d: 오류 :", 17); printf(" 제수가 0 입니다.\n", divisor); while (0); printf("%.3f / %.3f = %.3f\n", dividend, divisor, dividend / divisor); 60

자기참조구조체 자신과같은구조체형을포인트하는멤버를갖는구조체 예 struct list { int data; struct list *next; a; dat a next 61

프로그램 13.9 #include <stdio.h> 자기참조구조체 struct list { int data; struct list *next; ; int main(void){ struct list a = {1, NULL, b = {2, NULL, c = {3, NULL; a.next = &b; b.next = &c; c.next = &a; printf("a : %d, b : %d, c : %d\n", a.data, b.data, c.data); printf("a : %d, b(a.next->data) : %d, c(b.next->data) : %d\n", a.data, a.next->data, b.next->data); printf("a : %d, b(c.next->next->data) : %d, \ c(a.next->next->data) : %d\n", a.data, c.next->next->data, a.next->next->data); return 0; 62

자기참조구조체 struct list a = {1, NULL, b = {2, NULL, c = {3, NULL; a b c 1 NULL 2 NULL 3 NULL data next data next data next a.next = &b; b.next = &c; c.next = &a; a b c 1 2 3 data next data next data next b.next -> data? a.next -> next -> data? 63

프로그램결과 a : 1, b : 2, c : 3 a : 1, b(a.next->data) : 2, c(b.next->data) : 3 a : 1, b(c.next->next->data) : 2, c(a.next->next->data) : 3 64

동적메모리할당과자기참조구조체 자기참조구조체는동적메모리할당기법과함께사용됨 동적으로할당받은구조체는기존구조체가포인트하여유지함 동적메모리할당은 malloc() 과 calloc() 으로함 예 tmp = (struct list *)malloc(sizeof(struct list)); 65

동적메모리할당과자기참조구조체 동적으로할당받은메모리공간은포인터를통해구조체를다루는것과똑같이다루면됨 예 tmp = (struct list *)malloc(sizeof(struct list)); tmp -> data = 4; tmp -> next = NULL; tmp 4 data NULL next 66

동적메모리할당과자기참조구조체 동적으로할당받은메모리공간은어느방법으로든접근할수있게만들어야함 가비지 : 접근할수없는동적으로할당받은메모리공간 예 tmp = (struct list *)malloc(sizeof(struct list)); tmp -> data = 10; tmp -> next = NULL; tmp 가비지 10 data NULL next 4 data NULL next 67

동적메모리할당과자기참조구조체 가비지가발생하지않게하기위해서는이전포인터를잘관리해야함 예 tmp -> next = (struct list *)malloc(sizeof(struct list)); tmp -> next -> data = 10; tmp -> next -> next = NULL; 68

동적메모리할당과자기참조구조체 자기참조구조체를다루는프로그램은재귀함수를많이사용함 예제프로그램 문자열을링크드리스트로변환 예 nice h n i c e NULL d next d next d next d next 69

동적메모리할당과자기참조구조체 프로그램 13.10 #include <stdio.h> #include <stdlib.h> #define N 10 struct linked_list { char d; struct linked_list *next; ; typedef struct linked_list typedef ELEMENT ELEMENT; *LINK; LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; 70

동적메모리할당과자기참조구조체 프로그램 13.10 void print_list(link head){ if (head == NULL) printf("null\n"); else { printf("%c --> ", head -> d); print_list(head -> next); int main(void){ char input[n]; LINK h; printf(" 문자열입력 : "); scanf("%s", input); h = string_to_list(input); printf(" 변환리스트결과 : \n"); print_list(h); return 0; 71

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) 72

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( go ) 73

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( o ) string_to_list( go ) 74

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( o ) string_to_list( o ) head o string_to_list( ) string_to_list( go ) 75

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( o ) string_to_list( o ) head o string_to_list( ) string_to_list( go ) NULL 76

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( o ) string_to_list( o ) head o NULL string_to_list( go ) 77

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g string_to_list( o ) string_to_list( o ) head o NULL string_to_list( go ) 78

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g o NULL string_to_list( go ) 79

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h string_to_list( go ) head g o NULL string_to_list( go ) 80

동적메모리할당과자기참조구조체 프로그램 13.10 LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(element)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; main() : h = string_to_list( go ); h g o NULL 81

프로그램결과 문자열입력 : nice 변환리스트결과 : n --> i --> c --> e --> NULL 82

자기참조구조체를사용할때주의사항 포인터를다룰때에는함수를만들어서할것 InitNode(), InsertNode(), DeleteNode() 포인터를다루는함수를만들기전에그림을먼저그릴것 p1 p2... A C... q B NULL p1 p2... A C... q B 83

자기참조구조체를사용할때주의사항 p1 p2... A C... q 1 B 2 p1 p2... A C... q 2 B 1 84

자기참조구조체를사용할때주의사항 1. 포인터를선언할때초기화할것 int *p = NULL; 2. 포인터를사용하기전에그값을확인할것 if (p!= NULL){... // p 사용 else {... // 오류처리 85

자기참조구조체를사용할때주의사항 3. 할당받은메모리만큼만값을다루어야함 p = (int *)malloc(n * sizeof(int)); while (istrue()){ p[i] = x; i++; 86

자기참조구조체를사용할때주의사항 3. 할당받은메모리만큼만값을다루어야함 p = (int *)malloc(n * sizeof(int)); while (istrue() && (i < N)){ p[i] = x; i++; 87

자기참조구조체를사용할때주의사항 4. 포인터를다루는부분은독립함수로만들것 InitNode(), InsertNode(), DeleteNode(), 등 5. 동적메모리할당을받기위해 malloc() 이나 calloc() 문장을만들때적절한곳에 free() 문장도같이만들것 6. free() 를사용하여메모리를반납한후포인터에 NULL 값을배정할것 free(p) p = NULL; 7. 포인터를다루기전에그림을그려볼것 88

자기참조구조체를사용할때주의사항 * 자신이없으면다른대안을찾아볼것 가변길이배열 n = 10; int a[n]; 플렉시블배열멤버 ( 뒤에설명 ) struct s{ int num; int a[]; struct s d1 = malloc(sizeof(struct s) + 40); 89

교재외자료 스택 선형연결리스트로구현 선형연결리스트로구현한스택 st ack el em cnt dat a t op stack cnt top elem NULL data dat a data...... dat a NULL data 90

교재외자료 스택구현 stack.h #include <stdio.h> #include <stdlib.h> #define EMPTY 0 #define FULL 10000 typedef char data; typedef enum {false, true boolean; struct elem { // element on the stack data d; struct elem *next; ; 91

교재외자료 스택구현 stack.h typedef struct elem elem; struct stack { int cnt; // a count of the elements elem *top; // ptr to the top element ; typedef struct stack stack; void initialize(stack *stk); void push(data d, stack *stk); data pop(stack *stk); data top(stack *stk); boolean empty(const stack *stk); boolean full(const stack *stk); 92

교재외자료 #include "stack.h" 스택구현 - 함수 void initialize(stack *stk){ stk -> cnt = 0; stk -> top = NULL; void push(data d, stack *stk){ elem *p; p = malloc(sizeof(elem)); p -> d = d; p -> next = stk -> top; stk -> top = p; stk -> cnt++; 93

교재외자료 스택구현 - 함수 data pop(stack *stk){ data d; elem *p; d = stk -> top -> d; p = stk -> top; stk -> top = stk -> top -> next; stk -> cnt --; free(p); return d; 94

교재외자료 스택구현 - 함수 data top(stack *stk){ return (stk -> top -> d); boolean empty(const stack *stk){ return ((boolean) (stk -> cnt == EMPTY)); boolean full(const stack *stk){ return ((boolean) (stk -> cnt == FULL)); 95

교재외자료 스택 - 검사프로그램 #include "stack.h" int main(void){ char str[ ] = "My name is joanna Kelly!"; int i; stack s; initialize(&s); // initialize the stack printf(" In the string: %s\n", str); for (i = 0; str[i]!= '\0'; ++i) if (!full(&s)) push(str[i], &s); // push a char on the stack printf("from the stack: "); while (!empty(&s)) putchar(pop(&s)); // pop a char off the stack putchar('\n'); return 0; 96

교재외자료 스택 - 검사프로그램 출력 In the string : My name is Jonna Kelly! From the stack :!yllek annoj si eman ym 97

플렉시블배열멤버 두개이상의멤버를갖는구조체형정의에서크기가명시되지않은마지막배열멤버 C99 예 struct subject { int num; int grade[]; ; 98

플렉시블배열멤버 플렉시블구조체의크기는플렉시블배열멤버를제외한크기임 플렉시블구조체변수를선언하면플렉시블배열멤버는메모리할당을받지않음 struct subject { int num; int grade[]; ; sizeof(struct subject) : 4 struct subject science; science.num = 10; // OK science.grade[0] = 95; // 오류 99

플렉시블배열멤버 사용하기전에플렉시블배열멤버를위한메모리공간을할당받아야함 사용예 struct subject *science_p; science_p = (struct subject *) malloc(sizeof(struct subject) + 40); // grade[] 를위해 40 바이트할당 int 원소 10 개 // 40 대신 sizeof(int) * 10 이더좋음 science_p -> num = 20; science_p -> grade[4] = 85; // OK 100

플렉시블배열멤버 프로그램 13.11 typedef struct subject { int num; int grade[]; subject; int main(void){ int n, i, sum; subject *math_p; subject *c_p; printf(" 수학과목수강생수 : "); scanf("%d", &n); math_p = (subject *) malloc(sizeof(subject) + sizeof(int) * n); math_p -> num = n; printf(" 수학성적 %d 개를입력하세요.\n", math_p -> num); for (i = 0; i < math_p -> num; i++){ printf("%d 번째성적 : ", i); scanf("%d", math_p -> grade + i); 101

프로그램 13.11 플렉시블배열멤버 printf("c 과목수강생수 : "); scanf("%d", &n); c_p = (subject *) malloc(sizeof(subject) + sizeof(int) * n); c_p -> num = n; printf("c 성적 %d 개입력하세요.\n", c_p -> num); for (i = 0; i < c_p -> num; i++){ printf("%d 번째성적 : ", i); scanf("%d", c_p -> grade + i); printf("\n 수학성적 \n"); for (i = sum = 0; i < math_p -> num; i++){ printf("%d 번학생성적 : %d\n", i, math_p -> grade[i]); sum += math_p -> grade[i]; 102

프로그램 13.11 플렉시블배열멤버 printf(" 총점 : %d, 평균 : %.2f\n", sum, sum/(float)math_p -> num); printf("\nc 성적 \n"); for (i = sum = 0; i < c_p -> num; i++){ printf("%d 번학생성적 : %d\n", i, c_p -> grade[i]); sum += c_p -> grade[i]; printf(" 총점 : %d, 평균 : %.2f\n", sum, sum/(float)c_p -> num); return 0; 103

프로그램결과 수학과목수강생수 : 3 수학성적 3 개를입력하세요. 0 번째성적 : 78 1 번째성적 : 88 2 번째성적 : 92 C 과목수강생수 : 5 C 성적 5 개입력하세요. 0 번째성적 : 87 1 번째성적 : 90 2 번째성적 : 95 3 번째성적 : 71 4 번째성적 : 90 수학성적 0 번학생성적 : 78 1 번학생성적 : 88 2 번학생성적 : 92 총점 : 258, 평균 : 86.00 C 성적 0 번학생성적 : 87 1 번학생성적 : 90 2 번학생성적 : 95 3 번학생성적 : 71 4 번학생성적 : 90 총점 : 433, 평균 : 86.60 104

라이브러리 라이브러리목록은 ar 명령어로볼수있음 ar t /lib/libc.a libc.a : 표준 C 라이브러리 /lib : 디폴트라이브러리디렉터리 프로그래머는자신의라이브러리를만들수있음 105

라이브러리만들기 라이브러리 함수 13.2(iszero.c) int is_zero(int num) { if (num) return 0; return 1; 1..o 파일만들기 $ gcc -c iszero.c 2. 라이브러리만들기 $ ar ruv iszero.a iszero.o $ ranlib iszero.a 106

프로그램 13.12 (main.c) #include <stdio.h> 라이브러리 int quotient, rem; // 전역변수선언 int divide(int, int); int main(void){ int a = 10, b = 3; if (divide(a, b)) printf("0 으로나눌수없습니다.\n"); else printf("%d / %d : 몫은 %d 이고나머지는 %d 입니다.\n", a, b, quotient, rem); return 0; 107

라이브러리 프로그램 13.12 (divide.c) int divide(int dividend, int divisor){ extern int quotient, rem; // 전역변수참조선언 if (is_zero(divisor)) return -1; quotient = dividend / divisor; rem = dividend % divisor; return 0; 108

라이브러리 사용자라이브러리를사용할경우컴파일할때사용자라이브러리를명시하면됨 $ gcc o divide main.c divide.c iszero.a main.c 와 divide.c 에서호출하는함수가 main.c 와 divide.c 에정의되어있지않으면 iszero.a 라이브러리를먼저검색하고없으면표준라이브러리에서검색함 109

신호 프로세스 : 실행중인프로그램 신호는프로세스에게외부환경의변화나오류를전달할때사용 일반적으로신호는비정상적인사건에의해생성되고프로그램에게전달되어프로그램을종료하게함 0 으로나누기 잘못된메모리참조 control-c 110

신호 <signal.h> 에신호와관련된매크로와함수정의 많이다루어지는신호관련매크로 #define SIGINT 2 // 인터럽트 #define SIGILL 4 // 비정상연산 #define SIGFPE 8 // 부동소수점예외 #define SIGKILL 9 // KILL #define SIGSEGV 11 // 세그먼트위반 #define SIGALRM 14 // 알람클락 111

신호 신호를다루는함수 signal() void (*signal(int sig, void (*func)(int)))(int); sig : 신호종류 func : 신호처리기 sig 와 func() 함수를연결하는함수 sig 신호가발생하면 func() 가실행됨 예 signal(2, func); 2 번신호 (control-c) 가발생하면프로그램이종료되는것이아니라 func() 함수가호출됨 보통숫자대신매크로를사용함 signal(sigint, func); 112

신호 프로그램 13.13 #include <stdio.h> #include <stdlib.h> #include <signal.h> void cntrl_c_handler(int sig){ char answer[4]; printf("%d 번신호가발생했습니다.\n", sig); printf(" 계속하시겠습니까? (y/n) "); scanf("%s", answer); if ((answer[0] == 'n') (answer[0] == 'N')) exit(1); 113

신호 프로그램 13.13 int main(void){ int i = 0; signal(sigint, cntrl_c_handler); while (1) { printf("%4d", rand() % 1000); if ((++i % 5) == 0) { i = 0; putchar('\n'); return 0; // SIGINT : control-c 114

프로그램결과.... 919 949 558 933 245 846 518 203 752 403 792 608 494 676 908 <control-c> 2 번신호가발생했습니다. 계속하시겠습니까? (y/n) y.... 521 192 309 458 219 278 64 898 339 282 772 272 167 924 291 761 751 31 874 340 319 423 962 902 49 440 730 518 810 154 <control-c> 2 번신호가발생했습니다. 계속하시겠습니까? (y/n) n $ 115

신호 신호처리기로사용할수있는매크로 #define SIG_DFL ((void (*)(int)) 0) // 신호가발생했을때디폴트행동을취하게함 #define SIG_IGN ((void (*)(int)) 1) // 신호가발생했을때무시하게함 예 signal(sigint, SIG_IGN); 인터럽트가발생하면무시함 signal(sigint, SIG_DFL); 인터럽트가발생하면디폴트동작을다시하게함 인터럽트를위한디폴트동작은프로세스종료임 116

신호 신호중 9 번신호 (SIGKILL) 는사용자가임의로다룰수없음 signal() 함수로 SIGKILL 신호와사용자신호처리기를연관시켜도 SIGKILL 신호가발생하면그프로세스는무조건종료함 117