함수 Heeseung Jo
이장의내용 함수개요프로시저함수호출메커니즘변수와유효범위재귀함수매크로함수 2
함수개요
함수개요 함수란? 함수 (function): 상자수 ; 상자에수를넣으면수가나옴 자동판매기와유사함 수학에서함수는대응관계 (mapping) 를의미함 함수주변상황 인수 : 함수에들어가는값 - 정의구역 (domain) 의원소 리턴값 : 함수가되돌려주는값 - 공변역 (co-domain) 의원소 4
C 언어에서함수 프로그래밍분야에서함수란? 작은프로그램 (subprogram) 인수를받아서리턴값을내는모듈 수학함수와다른점 프로그래밍에서함수는부수효과 (side-effects) 를낼수있음 심지어리턴값이아예없을수도있음 리턴값이없는함수를프로시저 (procedure) 라고함 printf 의부수효과예 : 5
함수정의방법 C 함수정의형태 리턴타입함수이름 ( 매개변수목록 ) { 문장들 } 함수헤더 (function header) 함수본체 (function body) C 함수정의예 int add1(int x) { return x + 1 ; } x 예쁘게들여쓰기 add1 int add1(int x) { return (x + 1); } x+1 6
return 문과리턴타입 return 문 형식 : return 값 ; 함수가어떤값을돌려주는지명시 리턴값은리턴타입 (return type) 과일치해야함 double half(int x) { return (x / 2.0); } 7
add1half.c (1/2) 인수보다하나큰값을구하는함수 인수값의반을구하는함수 8
add1half.c (2/2) 사용자정의함수호출 9
함수프로토타입 함수프로토타입 (prototype) 이란? 함수사용방법만명시한것 어떤자료형의인수를몇개받고 어떤자료형의리턴값을내는지명시함 왜함수프로토타입이중요한가? 함수를사용 ( 호출 ) 하기전에함수정의나함수프로토타입선언중최소한하나는나타나야함 프로토타입작성예 int add1(int x, int y); double half(int x); 매개변수이름생략가능 int add1(int, int); double half(int); 10
prototype.c (1/2) 함수프로토타입선언후에는함수정의가나타나지않았어도선언한함수를사용가능 add1 과 half 의 prototype 11
prototype.c (2/2) add1 과 half 정의 12
프로시저
프로시저 C 함수분류 값리턴함수 (value-returning function): 값을리턴하는함수, 수학적함수와유사함 void 함수 (void functions): 값을리턴하지않는함수, 부수효과만을이용하여어떤작업을수행 - void 함수를 " 프로시저 (procedure)" 라고부르기도함 14
void.c ( 일부 ) 실행결과 : 정수를하나입력하세요. 123 123 의바로다음정수는 124 이고 123 의반은 61.5 입니다. 제가맞게계산했나요? 함수 add1 과 half 를이용하는 void 함수 이함수때문에 main 이간단해졌다. 15
작명법에관한도움말 이름은구체적으로작성 적절하지못한이름 : process(); test(); control(); 적절한이름 : - dot_product(); 두벡터의내적을구하는함수 - all_positive(); 컨테이너원소가모두양수인가검사 - rotate_right(); 순차컨테이너고리형태로간주하고원소를우측으로이동 여러단어로이루어진이름은... 밑줄을이용하는방식 : 전통적인 C 프로그래밍방식 낙타체 : 대소문자를번갈아사용해가며단어를구별하는방식 - Java 에서사용하는방식 - dotproduct(); allpositive(); rotateright(); 16
하향식프로그래밍 하향식프로그래밍 (Top-Down Programming) 단계 문제를한문장으로기술 주어진문제를해결하기위해필요한세부작업을기술 더이상수행할세부작업이없을때까지다음을반복 - C 에서기본적으로제공하는기능을이용하여세부작업을바로구현할수있다면구현 - 세부작업이여전히큰규모라면단계 2 를반복하여다시작업을세분화 하향식프로그래밍의특징 바로구현할수있을단계까지문제를점진적으로세분화하여내려가는방식 (stepwise refinement) 17
하향식프로그램밍예 Top: 정수를하나읽어들인후, 그수의바로다음정수와그수를 2 로나눈수를출력 단계별세분화 18
topdown2.c (1/2) ' 전체문제 ' 를기술하는데필요한함수들 함수 main 에는 ' 전체문제 ' 를기술 19
topdown2.c (2/2) 20
함수호출메커니즘
함수호출과복귀개요 기본적인방식 호출자함수 A 는함수 B 를호출하면수행을멈춤 호출된함수 B 는 1. return 문을만나거나 2. 함수몸체끝에도달할때까지수행 호출된함수 B 의수행이끝나면호출지점바로다음으로복귀 복귀지점 복귀지점은문장단위가아닐수도있음 예를들어, double result = add1(2) * half(3); printf("result = %f\n", result); 에서 half() 가 add1() 보다먼저호출되었다면그복귀지점은 add1(2) 가됨 23
제어흐름예 main 함수에서 f 를호출했다고하면 f 는두가지방식으로복귀가능 25
자료흐름 : 인수전달 함수인수 (argument) 는값을구하여매개변수 (parameter) 에 " 복사 " 하여전달 예 : main 함수에서 print_sign(5); 를호출했을경우 26
자료흐름 : 임시변수사용 인수가수식인경우에는호출자의임시공간 ( 임시변수 ) 를활용하여수식값을구한후전달 예 : 다음과같이호출한경우수식 b - a 값은 main 의임시공간에서계산 27
자료흐름 : 리턴값전달 값반환함수호출 예 : 값반환함수호출은수식으로간주하기때문에리턴값도역시호출자의임시변수에저장 다음과같이호출한경우 read_int() 값과 num*num 값은임시공간에저장 28
sign.c 제어흐름 자료흐름 29
변수와유효범위
유효범위 유효범위 (scope) 란? 어떤변수를사용할수있는프로그램내의범위를그변수의유효범위라고함 유효범위를두지않는다면모든변수를프로그램전체에서사용할수있어야하므로매우복잡해짐 변수유효범위의결정 변수의유효범위는선언된위치에따라결정됨 유효범위에따라 - 지역변수 (local variable) - 비지역변수 (nonlocal variable) 32
유효범위에따른변수분류 지역변수 (local variable) 함수내에선언된변수 함수내부에서만볼수있음 함수가호출될때생성 주의 : 지역변수이지만정적변수로선언되는경우도있음 비지역변수 (nonlocal variable) 함수밖에선언된변수 여러함수에서볼수있음 - 전역변수 (global variable): 프로그램전체에서볼수있음 - 파일범위변수 (file scope variable): 같은파일내의함수에서만볼수있음 프로그램이시작할때생성 33
비지역변수를통한데이터전달 가능하지만, 비지역변수를통해데이터를전달하면데이터를전달하는함수와데이터를전달받는함수외의함수도그데이터를볼수있음 불필요한의존성 (dependency) 이발생하므로바람직하지않음 매개변수를통해데이터를전달하는것이좋은방법 ' 호동 ' 함수가 ' 선영 ' 함수에게사랑을고백하려면, 칠판에고백하는것보다 ' 선영 ' 의다이어리에몰래써두는것이더안전함 34
nonlocal.c 비지역변수 GX 는세함수에서모두사용가능 이렇게선언된 GX 는전역변수 실행결과 : [main 에서 ] GX = 12345 [f 에서 ] GX = 12345 [g 에서 ] GX = 12345 35
파일범위변수 다른파일에서 GX 를볼려면 extern int GX; 선언을해주어야함 함수밖에선언된변수중 static 으로선언된변수 파일범위변수는전역변수와는달리다른파일에서는볼수없음 nonlocal1.c 볼수있음 nonlocal2.c 볼수없음 37
지역정적변수 지역변수를선언할때, static 키워드를붙이면이변수도정적변수가됨 정적변수는함수영역이사라진다고해도사라지지않음 따라서이전호출종료시저장되어있던값을다음호출시사용할수있음 이런변수를 ' 역사에민감한변수 (history sensitive variable)' 라고함 38
count.c 정적변수초기화 모든정적변수는초기화해야함 초기화하지않았을경우엔 0 으로초기화됨 지역정적변수호출사이에값이보존된다. 실행결과 : count = 1 count = 2 count = 3 count = 4 count = 5 39
변수분류 유효범위 (scope): 해당변수를볼수있는범위지속시간 (lifetime): 변수가생성과소멸사이의시간 지속시간이길어짐 지속시간 동적변수 정적변수 유효범위 (dynamic variable) (static variable) 유효범위가넓어짐 지역변수 (local) 파일범위변수 (file-scope) 전역변수 (global) 함수본체내부에그냥선언선언불가선언불가 블록내부에 static으로선언함수외부에 static으로선언함수외부에그냥선언 41
재귀함수
재귀함수 재귀호출 (recursive call) 어떤함수가종료되지않은상황에서자신을다시호출하는것 재귀함수 (recursive function) 재귀호출을이용하는함수 재귀적인그림 43
fact.c 계승 (factorial) 정의 n! = n (n 1) 1 재귀적인계승정의 0! = 1 n! = n (n 1)! 재귀호출 실행결과 : 자연수를하나입력하세요 : 10 fact(10) = 3628800 입니다. 44
재귀함수의제어흐름 재귀함수의호출과리턴 재귀함수의경우에도호출수와리턴수는같음 따라서재귀함수는여러번호출되었다가다시여러번리턴 재귀함수의장단점 장점 : 프로그램구조가깔끔 단점 : 재귀함수의호출과리턴에따른부담으로인해수행속도가느려질수있음 45
매크로함수
max.c : 매크로함수 매크로함수 인수를받는매크로 함수와유사하지만실제로함수는아님 MAX(i, j) 는전처리기를거치면 (i > j)? i : j 로확장 실행결과 : 두수를입력하세요. 2 3 MAX(2, 3) = 3 47
매크로오류 매크로오류 매크로함수는실제로함수가아니므로예기치못한오류를발생시킬수있음 매크로오류예 int i = 2, j = 3, max = 0; max = MAX(++i, ++j); #define MAX(x, y) x > y? x : y printf("i = %d, j = %d, max = %d\n", i, j, max); 어떤값이출력될까? i = 3, j = 5, max = 5 이유는? max = (++i > ++j)? ++i : ++j; 48