Function Pointer란?

개발 노트 2008. 7. 14. 22:15 posted by 무병장수권력자


Function Pointer의 사용

작성자 : 김문규
최초 작성일 : 2008. 7.14

1. Function Pointer(함수 포인터)는 무엇일까요?

예제로 바로 보지요.

void func(int x)
{
  printf("x = %d\n",x);
}

main()
{
  int a = 10;
  int* b = &a;
 
void (*test)(int);
  test = func;
  func(a);
}


파란 색으로 두줄은 완전하게 동일한 것입니다.

C, C++에서는 포인터를 이용해서 메모리 영역을 직접 가리킬 수 있습니다. 일반 변수들이 그러한 것은 익히 잘 알고 있을 것입니다. 배열 역시 그러합니다.
예) int *a = 10; 여기서 a는 10이 저장된 실제 메모리의 위치를 가리킨다.
예) int a[10]; 여기서 a는 int가 저장되는 공간 10개가 배치된 메모리의 주소 위치를 가리킨다.

그렇다면, 함수는? 간단하게 생각하자면 함수는 배열과 매우 유사하다.
함수의 이름은 함수가 저장된 위치를 가리킵니다.
예) int (*func)(int); func는 int 변수, int 반환값을 가지는 함수가 저장된 주소 위치를 가리킵니다.

별거 없지요? ^^ 이상 함수 포인터의 개념이었습니다.

2. 그럼 언제 사용하는 걸까요?

과연 언제 사용하면 좋을까요? 오픈 소스를 많이 보면 쉽게 용례를 찾을 수 있지만 생각나는 것 하나만 공유하고자 합니다.

예를 들어보지요.
그래픽 라이브러리를 이용해서 그림을 그리는 프로그램을 가정하겠습니다. 이 프로그램은 다양한 그래픽 환경에 대응해야 한다는 조건을 가집니다. (mplayer와 같은 플레이어에서 다양하게 video out을 지원하는 경우를 생각해 보면 되겠습니다.)

이 때, 우리는 두가지의 구현 방식을 고민하게 됩니다. (더 있을 수도 있겠지요? ^^)

(코드는 의미로만 해석해주길....)

(1) 단순 통짜로!

paint.c
if(lib == "X11") X11paint();
else if (lib == "SDL" ) SDLPaint();
.......

(2) 조금 세련되게

paint.h
static vo_driver_t vo_drivers [ ] = {
#ifdef LIBVO_X11
    {"x11", X11paint},
#ifdef LIBVO_SDL
    {"sdl", SDLPaint},
........
}

paint.c
    paint();

load_vo.c
for (........) {
    if(library == vo_drivers[i].type) paint = vo_drivers[i].func;
}

차이는 뭘까요?
구현에 있어 계층화(layering) 이루어져 있는가 하는 것입니다. 계층화는 초심자에게 프로그램을 더욱 복잡한 것처럼 보이게 하지만 실은 유지 보수를 쉽게하고 개념적인 이해를 더욱 빠르게 도와줍니다. 관심의 대상을 잘게 분리할 수록 집중해야 하는 부분이 명확해지는 것은 당연하지 않을까요?

구현(1)은 새로운 driver가 추가 될 때마다 paint.c를 수정해야 합니다.
반면에, 구현(2)에서는 하위 계층의 구현이 아무리 바뀌거나 추가 되어도 paint.h만 바꾸면 됩니다.
 
paint.c를 이용해서 플레이어 스킨 UI를 개발하는 사람이 있고, X11Paint()를 개발하는 사람이 다르다면 (2)방식이 조금이나마 더 co-work이 쉬울 것입니다. 그렇겠지요? ^^;

앞서도 말했지만 꼭 이것이 함수 포인터를 사용하는 경우는 아닐 것입니다. 단지 하나의 경우임을 생각해 주길 바랍니다.

이상! 함수 포인터의 사용 예시 였습니다.