Computer Science/C언어

[C언어] 함수 포인터에 대해

무니화니 2022. 9. 21. 11:23

보통 C언어를 사용하면서 포인터는 변수를 가리킬 때 사용하고는  한다.

그러나 포인터는 함수의 시작 주소도 나타낼 수 있다.

이를 우리는 '함수 포인터'라고 한다.

 


함수 포인터란?

 

함수 포인터에는, 3가지 부분으로 나뉜다.

type (*function_name) (arguments);

함수의 자료형

함수의 이름을 대신하여 호출할 수 있는 함수 포인터

매개변수

 

로 이루어진다.

 

#include <stdio.h>
int sum(int, int);

int main() {
	int (*fp)(int, int);
	fp = sum;
	printf("%d\n", fp(10, 20));  //1
    printf("%d\n", sum(10,20));  //2
    printf("%d\n", (*sum)(10,20));  //3
	return 0;
}


int sum(int a, int b) {
	return (a + b);

}

위와 같은 예시로, fp라는 함수 포인터를 설정하여, sum이라는 함수와 동일한 역할을 수행할 수 있다. (//1)

당연하지만, 함수 포인터를 이용하지 않고도 함수 호출이 가능하다. (//2)

마지막은 함수 명을 간접 참조 연산자인 *을 이용해서 사용해본 예시인데, 함수명 또한 주소로 나타낼 수 있음을 증명한 바이다. (그래서 함수 포인터도 가능한 것) (//3)

 

그렇다면, 왜 2번처럼 함수를 나타내면 되는데, 굳이 1번처럼 함수 포인터를 사용하는 것일까?


함수 포인터를 사용하는 이유

'그냥 함수를 사용할 때 그대로 함수를 사용하면 되지, 왜 굳이 함수 포인터를 사용해야 하는가?' 라는 질문을 할 수도 있는데, 쉽게 설명하면 코드를 줄이려고 쓰는 것 같다.

 

Callback 함수를 이용할 때 요긴하게 사용된다.

callback함수는 다른 인수의 인자로서 사용될 때, 특정 상황에서 호출되어지는 함수를 의미한다.

 

 

예를 들면 (대부분의 책에서 사용되는 예시이다)

#include <stdio.h>
void func(void(*fp)());
void hi();
void hey();
int main() {
	int num;
	scanf("%d", &num);
	switch (num) {
	case 1:
		func(hi);
		break;
	case 2:
		func(hey);
		break;
	}
	return 0;
}
void func(void (*fp)()){
	fp();
 }

void hi() {
	printf("hi");
}
void hey() {
	printf("hey");
}

사용자가 1을 입력하면, hi라는 함수를 실행하고,

사용자가 2를 입력하면, hey라는 함수를 실행한다.

func이라는 함수로 '인사'라는 기능을 사용하는 함수라고 정의할 수 있겠다.

 

hi나 hello 대신에 'ni hao'라는 기능을 추가하고  싶을 때,

ni hao라는 함수를 새로 만들어서

func(nihao)

 

만 실행하게 된다면 또 사용이 가능하다.

 

 

그만큼 함수 포인터를 사용하게 된다면,

용이하게 버전관리를 할 수 있다.