C Language 함수 (Function) Doo-ok Seo clickseo@gmail.com http://
목 차 함수의기본개념 함수와포인터 기억클래스 2
함수의기본개념 함수의기본개념 함수의기본개념 사용자정의함수 함수와포인터 기억클래스 3
함수의기본개념 함수란무엇인가? 함수는필요한데이터를주면정해진행동을하고원하는값을만들어서돌려준다 데이터만주면내가그모든값의평균을구해주지 잘정의된일을처리하는기본단위 나에게식빵을주면구운식빵을만들어드리죠 나에게정수 2 개만주면그곱을만들어주겠어 4
함수의기본개념 (cont d) 왜함수를사용하는가? 분할과정복 (Divide-and Conquer) 어떤문제를해결하기위해여러개의작은문제로쪼개는것 사람이일을처리하는방법도비슷하다. 프로그램의작성이용이 반복적인일을수행하는경우원시파일의크기를줄일수있다. 함수단위로프로그램을구성함으로써얻을수있는장점 함수의호출을통한프로그램의간략화 함수의재사용을통한프로그램구성의편리성 표준함수들을이용한프로그램구현의용이성 함수단위로데이터에접근하는방법 ( 변수의지역성 ) 을통해자료에대한제어의용이성 5
함수의개념 함수의기본개념 (cont d) C 에서함수의사용 구조화프로그래밍에서사용한모듈의개념을실질적으로구현한형태 사용자가원하는요구에대한각각의기능들을피 - 호출함수로작성 호출함수 (main 함수 ) 에서호출하여원하는작업을수행토록구현 6
함수의기본개념 (cont d) 함수의개념 (cont d) 함수들간의호출관계 상위호출모듈에의해하위피 - 호출모듈이호출되는구조 상위호출모듈에의해서만대화가가능 데이터전달 ( 매개변수전달 ) 값넘기기 (Pass By Value) 호출모듈에게피-호출모듈이전달할데이터의값을복사하여전달 값이직접적으로변경되지않음 참조넘기기 (Pass By Reference) 호출모듈에게피-호출모듈이전달할데이터의메모리상의주소 ( 참조 ) 를전달 호출된데이터의값이변경가능 중요한오류의원인이될수도있음 7
함수의기본개념 (cont d) 구조화프로그램설계 하향식설계와구조화프로그래밍원리 하향식설계 전체프로그램을기능별로모듈 (module) 로세분화하여프로그램을구성하는설계방법 구조화프로그래밍기법 모듈별로기능들을세분화한후에순차, 선택, 반복기법을이용하여프로그램하는기법 구조차트를그려서기능들을세분화함 8
구조화프로그램설계 (cont d) 하향식설계와구조화프로그래밍원리 (cont d) 하향식프로그램을위해구조차트 (Structure chart) 작성 작성규칙 함수의기본개념 (cont d) 구조차트는위에서아래로... 왼쪽에서오른쪽으로... 호출모듈 피호출모듈 9
사용자정의함수 함수선언 컴파일러에게함수의이름과결과값의타입 (return type), 인자의타입들을알려준다. int Clickseo(int, int); 반환형식 함수이름 전달인수 #1 의형태 전달인수 #2 의형태 ( 케이크 ) ( 요리사 ) ( 밀가루 ) ( 우유 ) 10
사용자정의함수 (cont d) 함수정의 함수에대한코드를생성하는작업 함수의구성요소 함수헤더 함수몸체 반환형식 함수명 형식매개변수 함수헤더 return_type function_name (formal_parameter_list) 함수몸체 // 지역변수선언... ( 실행할문장 )... 11
함수호출관계 사용자정의함수 (cont d) #include <stdio.h> 호출함수 void greeting(void); int main(void) greeting(); return 0; // 함수프로토타입선언 // 함수호출 void greeting(void) printf( Hello World!!! ); return; 피호출함수 12
사용자정의함수 (cont d) 매개변수를갖지않는 void 함수 #include <stdio.h> void greeting(void); int main( ) greeting( ); return 0; void greeting(void) printf( 두기와함께하는 C 여행!! ^^v ); result = greeting(); // 매개변수가없는함수를대입하고자하면오류 13
사용자정의함수 (cont d) 매개변수를갖는 void 함수 #include <stdio.h> void printx(int x); int main( ) int a=5; printx(a); return 0; void printx(int x) printf( %d, x); result = printx(a); // 매개변수가없는함수를대입하고자하면오류 14
사용자정의함수 (cont d) 전달값을갖는함수 #include <stdio.h> int sqr(int x); int main( ) int a, b; scanf( %d, &a) int sqr(int x) int result; b = sqr(a); printf( %d squared : %d n, a, b); result = x * x; return 0; return result; b = sqr(a); // 전달값을가질수있는함수에서매개변수를전달하여서브함수에서연산을수행한후에결과를 return 문을통해반환 15
함수작성의예 #1 사용자정의함수 (cont d) #include <stdio.h> int main(void) int a, b, sum; scanf("%d %d", &a, &b); sum = a + b; a, b 의두정수를더하는명령행을하나의함수로작성 printf("%d + %d = %d n", a, b, sum); return 0; 16
함수작성의예 #2 사용자정의함수 (cont d) #include <stdio.h> int ADD(int, int); int ADD(int a, int b) void main(void) int a, b, sum; int sum; scanf("%d %d", &a, &b); sum = ADD(a, b); printf("%d + %d = %d n", a, b, sum); sum = a + b; return sum; // return a + b; return 0; 17
Output type Input type 사용자정의함수 (cont d) int factorial(int n ) input 값의저장소 int s=1; for (i=1; i<=n; i++) s *= i; int 5 input return s; output 값 void main() input 값 int x; x = factorial(5); printf( %d, x); Output 값의저장소 n factorial s int x output 18
사용자정의함수 (cont d) 값에의한함수호출 : call by value push pop swap( ) 함수가종료되 면형식인자 a, b 와변 수 temp 는메모리에서 10 temp 자동소멸된다. a 10 b 20 swap(a, b); 10 20 20 10 a b main( ) 의메모리스택 swap( ) 의메모리스택 19
프로그램예제 : 값에의한호출 --swap() (1/2) #include <stdio.h> 사용자정의함수 (cont d) void swap(int, int); // 함수원형 int main(void) int a, b; a = 5; b = 7; printf( swap() 함수호출전 : a = %d, b = %d \n", a, b); // 호출전 a, b 값 swap(a, b); // a와 b의값전달 printf("swap() 함수호출후 : a = %d, b = %d \n", a, b); // 호출후 a, b 값 return 0; 20
프로그램예제 : 값에의한호출 --swap() (2/2) void swap(int x, int y) int 사용자정의함수 (cont d) temp; temp = x; x= y; y= temp; printf("swap() 함수내부에서 : x = %d, y = %d\n", x, y); 21
함수와포인터 함수의기본개념 함수와포인터 함수인자포인터 포인터를반환하는함수 기억클래스 22
함수인자포인터 (cont d) 참조에의한함수호출 : call by reference push a 10 1004 1 b 20 1000 2 swap(&a, &b); main( ) 의 메모리스택 10 1004 1000 b swap( ) 의메모리스택 temp a pop &a 와 &b 는 main() 함수에있는 a 와 b 의메모리주소이다. a 20 a와 b의값이바뀌었다. b 10 main( ) 의 메모리스택 push 1004 1000 주소참조 10 1004 1000 b swap( ) 의메모리스택 temp a pop temp = *a; *a = *b; *b = temp; 은결과적으로 main() 함수의 a 와 b 값을바꾸게된다. 23
프로그램예제 : 참조에의한호출 -- swap() (1/2) #include <stdio.h> 함수인자포인터 (cont d) void swap(int *, int *); int main(void) int a, b; a = 5; b = 7; printf("swap() 함수호출전 : a = %d, b = %d\n", a, b); // 호출전a,b값 swap(&a, &b); // a와 b의주소전달 printf("swap() 함수호출후 : a = %d, b = %d\n", a, b); // 호출후a,b 값 return 0; 24
프로그램예제 : 참조에의한호출 -- swap() (2/2) void swap(int *x, int *y) int temp; 함수인자포인터 (cont d) temp = *x; *x = *y; *y = temp; printf( swap() 함수내부에서 : x = %d, y = %d\n", *x, *y); 25
프로그램예제 : 포인터를반환하는함수 (1/2) #include <stdio.h> int *smaller(int *, int *); int main(void) int a, b; int *p; 포인터를반환하는함수 printf(" 두정수를입력하시오 : "); scanf("%d %d", &a, &b); p = smaller(&a, &b); printf("\n 최소값 : %d \n", *p); return 0; int *smaller(int *px, int *py) return *px < *py? px : py; 26
기억클래스 함수의기본개념 함수와포인터 기억클래스 기억클래스 지역변수와전역변수 자동변수와정적변수 외부변수 레지스터변수 27
기억클래스 (storage class) 기억클래스 컴퓨터내부기억장치 : CPU 레지스터, 주기억장치 주기억장치 데이터영역 : 전역변수, 정적변수 스택 (stack) 영역 : 정적할당 (static allocation) 힙 (heap) 영역 : 동적할당 (dynamic allocation) CPU 의레지스터 스택 힙 데이터영역 프로그램영역 28
기억클래스 (cont d) 변수의통용규칙 (scope rule) 함수외부에서선언된변수는선언된위치부터파일의끝까지 유효하다. 외부변수, 정적외부변수 함수내부에서선언된변수는안에서만유효하다. 지역 ( 자동 ) 변수, 레지스터변수, 지역정적변수 복합문의블록안에서선언된변수는선언된위치부터그블록의 끝까지유효하다. 지역 ( 자동 ) 변수, 레지스터변수 함수인자로사용된형식인자는함수와생명력을같이한다. 29
기억클래스 (cont d) 기억장소활용에따른변수의종류 변수의종류 예약어 생존기간 유효범위 초기화 초기화값 자동변수 (auto) 일시적 지역적 수행시 임의값 레지스터변수 register 일시적 지역적 수행시 임의값 ( 내부 ) 정적변수 static 영구적 지역적 컴파일시 0 ( 외부 ) 정적변수 static 영구적 전역적 컴파일시 0 외부변수 (extern) 영구적 전역적 컴파일시 0 30
지역변수와전역변수 지역변수 (local variable) 함수또는어떠한블록안에정의된변수 사용범위가함수내부로제한 ( 블록안에서만참조가능 ) 함수가호출되면생성되었다가리턴하면소멸된다. ( 자동변수, automatic variable) 서로다른함수에같은변수명사용가능 지역변수의초기화 함수가호출될때마다초기화되고리턴될때메모리를반납한다. 초기값을갖지않는지역변수는임의의값을가짐 사용예 : auto, register, 함수내선언의 static 지역변수는함수가호출될때메모리상에올라갔다가, 함수가종료되면메모리상에서사라진다. 31
지역변수와전역변수 (cont d) 전역변수 (global variable) 함수외부에서선언 모든함수가함께사용하는공유변수의특징 프로그램시작시생성되고종료될때까지할당된메모리유지 같은이름의전역변수는하나이상사용할수없다. 전역변수의초기화 프로그램시작시초기화되어종료시까지유지한다. 초기값을지정하지않은경우 0 으로초기화된다. 사용예 : extern, 함수외선언의 static 전역변수와정적변수의사용은최대한피해야한다 32
지역변수와전역변수 (cont d) int mode; int main() char ch; 전역변수의사용 int value, temp; mode = 1; value = MODE(ch, temp); ch 의유효범위 mode의유효범위 mode 는함수외부에서선언된전역변수로선언된위치부터파일끝까지영향력을미친다.. int f(char ch, int temp) int found = 0; if ( ) mode = 2; return found; 전역변수의사용 ch, temp, found 의유효범위 전역변수는함수외부에서선언되어모든함수가공유하면서사용가능하다. 지역변수는함수안에서선언되어함수와생명력을같이한다. 33
지역변수와전역변수 (cont d) 프로그램예제 : 지역변수 #include <stdio.h> int main() int a = 1, b = 2, c = 3; printf("%d %d %d\n", a, b, c); // 1 2 3 int b = 4; float c = 5.0; printf("%d %d %f\n", a, b, c); // 1 4 5.000000 a = b; int c; c = b; printf("%d %d %d\n", a, b, c); // 4 4 4 printf("%d %d %f\n", a, b, c); // 4 4 5.000000 printf("%d %d %d\n", a, b, c); // 4 2 3 return 0; 34
지역변수와전역변수 (cont d) 프로그램예제 : 증가 / 감소연산자와변수의지역성 #include <stdio.h> void main(void) int a = 10, b = 2; a += b++; printf("a = %d, b = %d\n", a, b); int a = 2; a += b; b -= a; printf("a = %d, b = %d\n", a, b); int b = 5; b *= a + 1; ++a; printf("a = %d, b = %d\n", a, b); printf("a = %d, b = %d\n", a, b); printf("a = %d, b = %d\n", a, b); 35
지역변수와전역변수 (cont d) 프로그램예제 : 전역변수 #include <stdio.h> int MemberCount; void AddMember() MemberCount++; printf("counting %d\n", MemberCount); int main() int i; for (i=0; i<10; i++) AddMember(); printf("total Member : %d\n", MemberCount); return 0; 36
지역변수와전역변수 (cont d) 프로그램예제 : 같은이름의전역변수와지역변수 #include <stdio.h> int value; // 전역변수 value void f(void); int main(void) int value = 10; // 지역변수 value printf("value : %d \n", value); f(); // f() 함수호출 printf("value : %d \n", value); return 0; void f(void) printf("value : %d \n", value); 지역내에서는지역변수가전역변수보다우선시된다. 37
자동변수와정적변수 자동변수 (auto variable) 선언된블록범위안에서자동으로생성되었다가자동으로사라진다 ( 지역변수의또다른표현 ). 예 ) 함수내부에서선언되는지역변수, 매개변수 스택사용 : 선언만하고초기화하지않으면쓰레기값을갖는다. auto data_type var_name; auto int a; a 1098 1008 15534 1004 2376 1000 다른변수가사용했던쓰레기값 (garbage) 선언만하고초기화를하지않으면어떤값이들어있는지알수없다. 38
자동변수와정적변수 (cont d) 정적변수 (static variable) 프로그램이끝나기전까지는메모리에계속적으로존재 지역변수의값을유지하기위해사용한다. 함수리턴후에도그값이소멸되지않고보관되며, 다시호출될때에는그직전의값참조한다. 함수내부에서선언되면해당함수안에서지역변수역할 함수외부에서선언되면전역변수역할 정적변수를전역변수로사용하는경우다른파일에서접근불가 정적변수의초기화 프로그램시작시초기화되어종료시까지유지한다. 초기값을지정하지않은경우 default 값으로초기화된다. char 형 : \0, int 형 : 0, float/double 형 : 0.0 static data_type var_name; 39
자동변수와정적변수 (cont d) 프로그램예제 : 정적변수 #include <stdio.h> void SUM(int); int main() int i; for (i=0; i<10; i++) SUM(i); // Error : 'sum' : undeclared identifier // printf("i = %d, sum = %d \n", i, sum); return 0; void SUM(int num) static int sum = 0; // 처음함수호출시한번만초기화 sum += num; printf("num = %d, sum = %d \n", num, sum); 40
외부변수 (extern variable) 외부변수 다른파일에정의된전역변수를선언만하고사용한다. 변수의영향력이가장넓다. 남용은금물 별도의기억장소할당없이기존의변수와기억장소공유 외부변수의장점 매개변수처럼전달이불필요하여시간이소비되지않으므로보다효율적 초기화가가능 통용범위가가장넓고생존기간이영구적이다 (all file). 외부변수의단점 프로그램을크고복잡하게만들어부작용의위험성 함수인수의주고받음이불분명해진다 ( 함수간의독립성상실 ). extern data_type var_name; 외부변수를남용하면모듈간의자료결합이강하게되어프로그램의구조를해치게되므로생산성이저하된다 ( 강결합성 ). 1 프로그램전체를총괄하는변수 2 프로그램전체의상황을기억하는변수 와같은경우에사용한다 ( 반드시그러해야되는것은아니지만...). 41
외부변수 (cont d) #include <stdio.h> int Mode; int f1(void); int f2(void); a.c 참조하겠다는뜻 b.c 가 a.c 의 Mode 를참조 int main() printf("### 외부변수 ### n"); #include <stdio.h> extern int Mode; int f1() Mode = 2; b.c 외부변수의선언과사용 printf( f1() Mode : %d %p n", Mode, &Mode); c.c #include <stdio.h> Mode = 1; printf("main Mode : %d %x n", Mode, &Mode); f1(); f2(); return 0; return 0; extern int Mode; int f2() Mode = 3; printf( f2() Mode : %d %p n", Mode, &Mode); return 0; 42
레지스터변수 레지스터변수 (register variable) 자동변수와기능적으로동일하다. 단, CPU 의레지스터에저장된다. 처리속도가빠르지만사용가능한레지스터개수에제한 보통 2,3 개정도의변수만레지스터변수로사용 주소연산자 (&) 를레지스터변수명앞에붙일수없다. 사용가능한데이터형도 char, int, 포인터형으로제한적 외부변수나정적변수는레지스터변수로정의할수없다. register data_type var_name; 43
프로그램예제 : 레지스터변수 #include <stdio.h> int main() register int i, j; double sum; 레지스터변수 (cont d) sum = 0; for (i=0; i<=10000; i++) for (j=0; j<=10000; j++) sum += i * j; printf("ans = %f\n", sum); return 0; 44
참고문헌 [1] 김일광저, C 프로그래밍입문, 한빛미디어, pp. 140 181. [2] 윤성우, 열혈강의 C 프로그래밍, 프리렉, pp. 217 258. [3] 김진외 7 인공역, 구조적프로그래밍기법을위한 C, 인터비젼, pp. 135 203. [4] 정재은, 다시체계적으로배우는 C 언어포인터, 정보문화사, pp. 206 221. [5] Brian W. Kernighan, Dennis M. Ritchie, The C Programming Language 2/e, 대영사, 94 124. 45