개발

함수 포인터(Function Pointer)란?

aahcbird 2019. 12. 2. 18:56

함수 포인터란?

  • C언어의 문법 중, 변수가 아닌 함수를 가리키는 포인터를 말한다.
  • int 자료형을 가리키는 int *, char 자료형을 가리키는 char * 포인터와 같이, 함수를 가리키는 포인터도 존재할 수 있다.

 

함수 포인터를 왜 쓰나요?

  • 함수 포인터는 콜백(callback) 매커니즘을 구현할 때 함수를 또 다른 함수의 인자(argument)로 넘겨주기 위해 주로 사용된다.
  • 또한, 여러 개의 함수를 배열로 관리하고자 할 때 사용할 수도 있다.

 

함수 포인터의 특징

  • 함수 포인터도 포인터이기 때문에, 일반적인 포인터와 마찬가지로 메모리 주소를 가리킨다.
  • 하지만 일반적인 포인터와 달리, 함수 포인터는 데이터가 아닌 코드의 위치를 가리킨다.
  • 마치 배열을 가리키는 포인터가 배열의 시작부분을 가리키는 것과 같이, 함수 포인터도 코드를 가리킬 때 코드의 시작부분을 가리킨다.
  • 또한 함수 포인터를 통해 메모리를 할당하거나 회수하는 것이 불가능하다.
  • 따라서 함수 포인터를 대상으로 malloc(), free() 함수를 사용할 수 없다.

 

함수 포인터의 문법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h> 
 
void fun(int num) {
    printf("%d\n", num);
}
 
int main() {
    void (*fun_ptr)(int);   // 함수 포인터 선언
    fun_ptr = &fun;         // fun() 함수의 주소값을 함수 포인터에 할당
 
    (*fun_ptr)(3);          // 함수 포인터를 사용하여 fun() 함수 호출
 
    return 0;
}
cs

 

  • 함수 포인터에 함수를 할당할 때에는, 선언한 함수 포인터와 할당하고자 하는 함수의 매개변수 타입반환형 타입이 일치해야 한다.
  • 함수 포인터를 선언한 후, 선언한 함수 포인터 fun_ptr에 fun() 함수를 할당했다.
  • 그렇게 하면 위 코드와 같이 함수 포인터 fun_ptr를 사용하여 fun() 함수를 호출할 수 있게 된다.
  • fun() 함수를 가리키는 fun이라는 함수의 이름도 사실 하나의 함수 포인터다.
  • 따라서 다음과 같은 문법도 유효하다.
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
void fun(int num) {
    printf("%d\n", num);
}
 
int main() {
    (*fun)(3);      // 함수 포인터를 사용하여 fun() 함수 호출
 
    return 0;
}
cs

 

  • 특이하게도 함수 포인터를 참조(reference)하거나 역참조(dereference)해도 함수 포인터는 여전히 함수의 코드를 가리키는 포인터로서 동작한다.
  • 다음 코드를 참조하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h> 
 
void fun(int num) {
    printf("%d\n", num);
}
 
int main() {
    void (*fun_ptr)(int);   // 함수 포인터 선언
 
    // 아래는 전부 같은 기능을 하는 코드이다.
    fun_ptr = &fun;
    fun_ptr = fun;
    fun_ptr = *fun;
    fun_ptr = **fun;
 
    return 0;
}
cs

 

  • 또한, 함수 포인터를 호출할 때 일반적인 함수 호출의 경우와 같이 *와 괄호의 생략이 가능하다.
  • 다음 코드를 참조하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h> 
 
void fun(int num) {
    printf("%d\n", num);
}
 
int main() {
    void (*fun_ptr)(int);
    fun_ptr = &fun;
 
    (*fun_ptr)(3);
    fun_ptr(3);
    (*fun)(3);
    fun(3);
 
    return 0;
}
cs

 

  • 함수 포인터를 여러개 담고 있는 함수 포인터 배열도 선언이 가능하다.
  • 아래의 코드는 두 수의 덧셈과 뺄셈을 수행하는 함수 포인터들의 배열이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h> 
 
void add(int num1, int num2) {
    printf("%d\n", num1+num2);
}
 
void sub(int num1, int num2) {
    printf("%d\n", num1-num2);
}
 
int main() {
    void (*fp[2])(intint);
    fp[0= &add;
    fp[1= &sub;
 
    (*fp[0])(35);
    (*fp[1])(35);
 
    return 0;
}
cs

 

 

참고한 자료