double func(int);
double(*fp)(int);
double *fn(int);
위 3개의 함수의 차이를 설명할 수 있는가?
결론부터 말하면 다음과 같다.
double func(int); /* int형을 받아 double로 반환해주는 func함수*/
double(*fp)(int); /* int형을 받아 double로 반환해주는 함수를 가리키는 포인터 fp*/
double *fn(int); /* int형을 받아 double에 대한 포인터를 반환하는 함수 fn */
함수를 가리키는 포인터. 말 그대로다.
그럼 위에서 함수 포인터는 셋 중 어떤것일까?
정답은 2번째 double(*fp)(int);이다.
함수를 가리키는 포인터 즉, 첫 번째 코드를 가리키는 포인터인 셈이다.
예시를 한번 보자.
#include <stdio.h>
int sum(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
void kuku(int(*calc)(int, int)) { //1
int i, j;
for (i = 1;i <= 9;i++) {
for (j = 1;j <= 9;j++) {
printf("%3d", (*calc)(i, j)); //2
}
putchar("\n");
}
}
int main() {
kuku(sum); //3
kuku(mul); //4
}
실행결과
3,4를 보면 함수 kuku의 인수는 함수(sum과 mul)이다.
(배열 이름이 배열의 첫 번째 요소의 포인터와 같은 것처럼, 함수 이름은 그 함수에 대한 포인터이다.)
3을 더 자세히 보면 kuku함수에게 다음과 같이 부탁하는 뜻이다.
함수 sum에 대한 포인터를 전달할게요.
그러니 포인터가 가리키는 함수(sum)의 실행으로 얻은 계산 결과(덧셈표)를 출력해주세요.
kuku 함수는 sum 함수에 대한 포인터를 매개변수 calc로 받는다.
받은 함수에 대한 포인터를 사용하는 코드가 2번 (*calc)(i,j)이다.
즉, sum함수에 대한 포인터가 매개변수 *calc인 셈이다.
*calc를 둘러싼 괄호()는 생략할 수 없다.
간접 연산자 *보다 함수를 호출하는 연산자(i,j)쪽이 우선순위가 더 높기 때문이다.
괄호를 생략하면 사실상 (int*)calc(i,j)가 될 것이다
함수에 대한 포인터는 매개변수 선언에서만 변수 이름 앞의 *와 ()를 생략한 형식으로 선언할 수 있다.
void kuku(int calc(int, int)) { //1
int i, j;
for (i = 1;i <= 9;i++) {
for (j = 1;j <= 9;j++)
printf("%3d", calc(i, j)); //2
putchar('\n');
}
}