컴퓨터프로그래밍 Computer Programming
14 함수와포인터활용
목차 1. 함수의인자전달방식 2. 포인터전달과반환 3. 함수포인터와 void 포인터 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 3
1. 함수의인자전달방식
함수에서값의전달 C 언어는함수의인자전달방식 기본적으로값에의한호출 call by value 방식 함수호출시실인자의값이형식인자에복사되어저장된다는의미 함수 increase(int origin, int increment) origin+= increment; 를수행하는간단한함수 함수호출시변수 amount 의값 10이매개변수인 origin 에복사되고, 20이매개변수인 increment 에복사 함수 increase() 내부실행 매개변수인 origin 값이 30으로증가 변수 amount 와매개변수 origin 은아무관련성이없음 origin 은증가해도 amount 의값은변하지않음 함수외부의변수를함수내부에서수정할수없는특징
함수에서값의전달
Source Code #01: callbyvalue.c 일반매개변수로실인자값을수정불가능 함수 increase() 첫번째매개변수를 int * 로수정 함수구현도 *origin += increment; 로수정하여구현 함수호출시첫번째인자가 &amount 이므로변수 amount 의주소값이매개변수인 origin 에복사 20 이매개변수인 increment 에복사 함수 increase() 내부실행 *origin 은변수 amount 자체를의미 *origin 을증가시키면 amount 의값도증가 main() 내부에서 amount 의값이 30 으로증가 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 7
참조에의한호출call by reference 포인터를매개변수로사용하면함수로전달된실인자의주소를이용하여그변수를참조가능 함수에서주소의호출 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 8
Source Code #02: callbyreference.c 매개변수가포인터이면실인자의값수정가능 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 9
배열이름으로전달 함수의매개변수로배열을전달하는것 배열의첫원소를참조매개변수로전달하는것과동일 배열을매개변수로하는함수 sum() 을구현 실수형배열의모든원소의합을구하여반환하는함수 함수 sum() 의형식매개변수는실수형배열과배열크기 첫번째형식매개변수에서배열자체에배열크기를기술하는것은아무의미가없음 double ary[5] 보다는 double ary[] 라고기술하는것을권장 실제로함수내부에서실인자로전달된배열의배열크기를알수없음 배열크기를두번째인자로사용 매개변수를 double ary[] 처럼기술해도단순히 double *ary 처럼포인터변수로인식 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 10
배열이름으로전달 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 11
배열크기로인자로사용 만일배열크기를인자로사용하지않는다면정해진상수를함수정의내부에서사용해야함 이런방법은배열크기가변하면소스를수정해야하므로비효율적 배열크기에관계없이배열원소의합을구하는함수를만들려면배열크기도하나의인자로사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 12
배열크기로인자로사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 13
Source Code #03: arrayparameter.c 함수 sum() 을구현하고이용 함수정의가구현되면함수원형을선언한뒤함수호출이가능 함수원형에서매개변수는배열이름생략가능 double[] 와같이기술가능 함수호출에서배열인자에는반드시배열이름으로 sum(data, 5) 로기술 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 14
다양한배열원소참조방법 배열 point 에서간접연산자를사용한배열원소의접근방법은 *(point + i) 배열의합을구하려면 sum += *(point + i); 문장을반복 문장 int *address = point; 배열 point 를가리키는포인터변수 address 를선언하여 point 를저장 문장 sum += *(address++) 으로도배열의합가능 배열이름 point 는주소상수 sum += *(point++) 는사용불가능 증가연산식 point++ 의피연산자로상수인 point 를사용할수없기때문 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 15
다양한배열원소참조방법 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 16
함수헤더에배열을인자로기술하는다양한방법 함수헤더에 int ary[] 로기술하는것은 int *ary 로도대체가능 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 17
Source Code #04: arrayparam.c 변수 ary 는포인터변수로서주소값을저장하는변수 증가연산자의이용이가능 연산식 *ary++s 는 *(ary++) 와같은의미 후위증가연산자 (ary++) 의우선순위가가장높기때문에 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 18
배열크기계산방법 배열이함수인자인경우, 대부분배열크기도함수인자로하는경우가일반적 배열크기 : ( sizeof( 배열이름 ) / sizeof( 배열원소 ) ) 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 19
Source Code #05: arrayfunction.c 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 20
다차원배열전달 이차원배열을함수인자로이용하는방법 이차원배열에서모든원소의합을구하는함수를구현 다차원배열을인자로이용하는경우 첫번째대괄호내부의크기를제외한다른모든크기는반드시기술 이차원배열의행의수를인자로이용하면보다일반화된함수를구현가능 함수 sum() 이차원배열값을모두더하는함수 함수 printarray() 는인자인이차원배열값을모두출력하는함수 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 21
다차원배열전달 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 22
이차원배열행과열 함수 sum() 을호출하려면배열이름과함께행과열의수가필요 이차원배열의행의수 : ( sizeof(x) / sizeof( x[0] ) ) 이차원배열의열의수 : ( sizeof(x[0]) / sizeof( x[0][0]) ) sizeof(x) 는배열전체의바이트수, sizeof(x[0]) 는 1행의바이트수 sizeof(x[0][0]) 은첫번째원소의바이트수 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 23
이차원배열행과열 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 24
Source Code #06: twoarrayfunction.c 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 25
가변인자가있는함수머리 함수 printf() 함수원형 첫인자는 char *_Format 을제외하고는이후에 표시 함수 printf() 를호출하는경우를살펴보면 출력할인자의수와자료형이결정되지않은체함수를호출 출력할인자의수와자료형은인자 _Format 에 %d 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 26
가변인자variable argument 함수에서인자의수와자료형이결정되지않은함수인자방식 처음또는앞부분의매개변수는정해져있으나 이후매개변수수와각각의자료형이고정적이지않고변하는인자 매개변수에서중간이후부터마지막에위치한가변인자만가능 함수정의시가변인자의매개변수는 으로기술 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 27
가변인자variable argument 함수 vatest 의함수헤드 void vatest(int n, ) 가변인자인 의앞부분에는반드시매개변수가 int n처럼고정적이어야함 가변인자... 시작전이전고정매개변수 가변인자를처리하는데필요한정보를지정하는데사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 28
가변인자가있는함수구현 함수에서가변인자를구현과정 필요매크로함수와자료형을위해헤더파일 stdarg.h 가필요 가변인자선언 : 마치변수선언처럼가변인자로처리할변수를하나만드는일 가변인자처리시작 : 선언된변수에서마지막고정인자를지정해가변인자의시작위치를알리는방법 가변인자얻기 : 가변인자각각의자료형을지정하여가변인자를반환받는절차매크로함수 va_arg() 의호출로반환된인자로원하는연산을처리 가변인자처리종료 : 가변인자에대한처리를끝내는단계 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 29
가변인자가있는함수구현 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 30
가변인자가있는함수구현 가변인자처리절차와가변인자가있는함수 sum(int numargs, ) 가변인자앞의첫고정인자인 numargs 는가변인자의수 int 형인가변인자를처리하여그결과를반환하는함수 가변인자... 시작전첫고정매개변수 이후의가변인자를처리하는데필요한정보를지정하는데사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 31
가변인자가있는함수구현 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 32
Source Code #07: vararg.c 가변인자를처리하는함수 avg(int count, ) 를구현 함수 avg() 의마지막고정인자인 count 는가변인자의수 double 형인가변인자를모두더한후평균을반환하는함수 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 33
Lab #01: 함수에서배열활용 함수에서인자로배열을사용하면배열은무조건참조에의한호출 함수에서배열의내용을수정하더라도그내용이원래의배열에그대로반영 함수 aryprocess() 는인자로사용된배열의내부원소를모두 1 증가시키는함수 일차원배열에서배열의크기 결과 ( 배열전체바이트수 )/( 배열원소바이트수 ) 2 4 6 8 10 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 34
2. 포인터전달과반환
매개변수와반환으로포인터사용 주소연산자 & 함수에서매개변수를포인터로이용하면결국참조에의한호출 함수원형 void add(int *, int, int); 에서첫매개변수가포인터인 int * 함수 add() 는두번째와세번째인자를합해첫번째인자가가리키는변수에저장함수 변수인 sum을선언하여주소값인 &sum 을인자로호출
Source Code #08: pointerparam.c 함수의결과를포인터로반환하는예 함수원형을 int * add(int *, int, int) 로하는함수 add() 반환값이포인터인 int * 두수의합을첫번째인자가가리키는변수에저장한후포인터인첫번째인자를그대로반환 add() 를 *add(&sum, m, n) 호출 변수 sum 에합 a+b 가저장 반환값인포인터가가리키는변수인 sum 을바로참조 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 37
주소값반환 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 38
Source Code #09: ptrreturn.c 함수 multiply() 인자인두수의곱을지역변수인 mult 에저장한후 &mult 로포인터를반환 지역변수는함수가종료되는시점에메모리에서제거되는변수 지역변수주소값의반환은문제를발생시킬수있음 제거될지역변수의주소값은반환하지않는것이바람직 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 39
상수를위한 const 사용 포인터를매개변수로이용하면수정된결과를받을수있어편리 이러한포인터인자의잘못된수정을미리예방하는방법 즉수정을원하지않는함수의인자앞에키워드 const 를삽입하여참조되는변수가수정될수없게함 키워드 const 는인자인포인터변수가가리키는내용을수정불가능 인자를 const double *a 와 const double *b 로기술 *a와 *b를대입연산자의 l-value 로사용불가능 즉 *a와 *b를이용하여그내용을수정불가능 상수키워드 const 의위치는자료형앞이나포인터변수 *a 앞에도가능 const double *a와 double const *a 는동일한표현 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 40
상수를위한 const 사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 41
Source Code #10: constreference.c 함수 devideandincrement(double *result, double *a, double *b) 포인터인자가모두 const 가아니므로그인자가가리키는변수의내용을모두수정가능 *a 와 *b 를나누어그결과를 *result 에저장한후 *a 와 *b 를각각 1 씩증가시키는함수 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 42
복소수를위한구조체 구조체 complex 실수부와허수부를나타내는 real 과 img 를멤버로구성 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 43
복소수를위한구조체 복소수complex number 실수의개념을확장한수로 a + bi로표현 여기서 a 와 b 는실수이며, i 는허수단위로 i2 = -1 을만족 a 는실수부, b 는허수부 복소수에서의사칙연산 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 44
인자와반환형으로구조체사용 함수 paircomplex1() 인자인복소수의켤레복소수 pair complex number 를구하여반환하는함수 복소수 (a + bi) 의켤레복소수는 (a - bi) 구조체는함수의인자와반환값으로이용이가능 다음함수는구조체인자를값에의한호출 call by value 방식으로이용 함수에서구조체지역변수 com 을하나만들어실인자의구조체값을모두복사하는방식으로구조체값을전달받음 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 45
인자와반환형으로구조체사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 46
인자와반환형으로구조체사용 이함수를참조에의한호출 call by reference 방식으로수정 paircomplex2() 는인자를주소값으로저장 실인자의변수 comp의값을직접수정하는방식 이함수를호출하기위해서는 &pcomp 처럼주소값을이용해호출 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 47
인자와반환형으로구조체사용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 48
Source Code #11: complexnumber.c 구조체를함수의인자로사용하는방식은다른변수와같이값에의한호출과참조에의한호출방식을사용가능 구조체가크기가매우큰구조체를값에의한호출의인자로사용한다면매개변수의메모리할당과값의복사에많은시간이소요 이에반해주소값을사용하는참조에의한호출방식은메모리할당과값의복사에드는시간이없는장점 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 49
Lab #02: 책정보를표현하는구조체전달 구조체 struct book 책이름과저자, 책번호 (ISB: 국제표준도서번호 International Standard Book Number) 표현 참조에의한호출로출력하는함수를구현 구조체 struct book 을자료형 book 으로정의 함수 print() 는인자가 (book *b) 으로구조체를포인터로받아책정보를출력 결과 제목 : 절대자바, 저자 : 강환수, ISBN: 123987 제목 : 파이썬웹프로그래밍, 저자 : 김석훈, ISBN: 2398765 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 50
3. 함수포인터와 void 포인터
함수포인터 함수주소저장변수 포인터의장점은다른변수를참조하여읽거나쓰는것도가능 함수포인터 하나의함수이름으로필요에따라여러함수를사용하면편리 함수포인터 pfun 은함수 add() 와 mult() 그리고 subt() 로도사용가능
함수포인터 함수포인터pointer to function 함수의주소값을저장하는포인터변수 즉함수포인터는함수를가리키는포인터 반환형, 인자목록의수와각각의자료형이일치하는함수의주소를저장할수있는변수 함수포인터선언 함수원형에서함수이름을제외한반환형과인자목록의정보가필요 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 53
함수포인터 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 54
함수포인터 변수이름이 pf인함수포인터를하나선언 함수포인터 pf는함수 add() 의주소를저장가능 함수원형이 void add(double*, double, double); 인함수의주소를저장 함수원형에서반환형인 void 와인자목록인 (double *, double, double) 정보필요 여기서주의할점 (*pf) 와같이변수이름인 pf 앞에는 * 이있어야하며반드시괄호를사용 만일괄호가없으면함수원형 pf는함수포인터변수가아니라 void * 를반환하는함수이름 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 55
함수포인터 물론위함수포인터변수 pf 함수 add() 만을가리킬수있는것이아니라 add() 와반환형과인자목록이같은함수는모두가리킬수있음 subtract() 의반환형과인자목록이 add() 와동일하다면 pf 는함수 subtract() 도가리킬수있음 문장 pf = subtract; 와같이함수포인터에는괄호가없이함수이름만으로대입 함수이름 add 나 subtract 는주소연산자를함께사용하여 &add 나 &subtract 로도사용가능 subtract() 와 add() 와같이함수호출로대입해서는오류가발생 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 56
함수포인터를이용한함수호출 다음예제에서함수 add() 의구현 함수 add() 에서 x + y의결과를반환하지않고포인터변수 z에저장 인자를포인터변수로사용하면함수내부에서수정한값이그대로실인자로반영 문장 pf = add; 함수포인터변수인 pf에함수 add() 의주소값이저장 변수 pf를이용하여 add() 함수를호출가능 포인터변수 pf 를이용한함수 add() 의호출방법은 add() 호출과동일 즉 pf(&result, m, n); 로 add(&result, m, n) 호출을대체 이문장이실행되면변수 result 에는 m + n의결과가저장 함수 add() 에서 m + n이반영된변수 result 를사용 pf(&result, m, n) 은 (*pf)(&result, m, n) 로도가능 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 57
함수포인터를이용한함수호출 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 58
Source Code #12: funcptr.c 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 59
함수포인터배열array of function pointer 원소로여러개의함수포인터를선언하는함수포인터배열 크기가 3인함수포인터배열 pfunary 는문장 int (*pfunary[3])(int, int); 으로선언 배열 pfunary 의각원소가가리키는함수 반환값이 int이고인자목록이 (int, int) 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 60
함수포인터배열array of function pointer 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 61
함수포인터배열선언 함수포인터배열선언구문 배열 fpary 의각원소가가리키는함수 반환값이 void 이고인자목록이 (double*, double, double) 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 62
함수포인터배열선언 함수포인터배열선언구문 배열 fpary 을선언한이후에함수 4 개를각각의배열원소에저장 배열 fpary 을선언하면서함수 4 개의주소값을초기화하는문장 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 63
Source Code #13: fptrary.c 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 64
void 포인터 void 포인터개념 포인터는주소값을저장하는변수 int *, double * 처럼가리키는대상의구체적인자료형포인터로사용이일반적 주소값이란참조를시작하는주소에불과 자료형을알아야참조할범위와내용을해석할방법을알수있음 void 포인터 (void *) 는무엇일까? void 포인터는자료형을무시하고주소값만을다루는포인터 대상에상관없이모든자료형의주소를저장할수있는만능포인터로사용가능 void 포인터에는일반포인터는물론배열과구조체심지어함수주소도저장가능 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 65
void 포인터 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 66
Source Code #14: voidptrbasic.c 다양한자료형의포인터를저장하는 void 포인터 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 67
void 포인터활용 void 포인터는모든주소를저장가능 가리키는변수를참조하거나수정이불가능 주소값으로변수를참조하려면결국자료형으로참조범위를알아야하는데 void 포인터는이러한정보가전혀없이주소만을담는변수에불과하기때문 void 포인터는자료형정보는없이임시로주소만을저장하는포인터 그러므로실제 void 포인터로변수를참조하기위해서는자료형변환이필요 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 68
void 포인터활용 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 69
Source Code #15: voidptr.c void 포인터로다양한자료의참조 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 70
Lab #03: 함수포인터배열의활용 배열크기가 3 인함수포인터배열을선언 각각더하기와빼기, 그리고곱하기를수행하는함수를각각저장 연산을수행하는방법과순서를나타내는문자열 "*+-" 를저장하여문자열순서대로곱하기, 더하기, 빼기를수행하는프로그램을작성 연산의피연산자는 3 과 5 로고정하여다음과같은결과로수행 * 결과 : 15 + 결과 : 8 - 결과 : -2 컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 71
컴퓨터프로그래밍 (Computer Programming) - 12 변수유효범위 72