함수 포인터란?
- 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])(int, int);
fp[0] = &add;
fp[1] = ⊂
(*fp[0])(3, 5);
(*fp[1])(3, 5);
return 0;
}
|
cs |
참고한 자료
'개발' 카테고리의 다른 글
스프링 프레임워크(Spring Framework)란? (0) | 2019.12.26 |
---|---|
펜윅 트리(Fenwick Tree)란? (0) | 2019.12.22 |
커버로스 프로토콜(Kerberos Protocol)이란? (1) | 2019.11.24 |
CSS 선택자(Selector)란? (0) | 2019.11.15 |
패키지 매니저(Package Manager)란? (0) | 2019.11.12 |