C/문법

[C] 함수 포인터

Rix 2021. 9. 14. 19:09

# 함수 포인터

함수를 가리킬 수 있는 포인터를 말한다.

함수에도 주소가 존재한다!

 

# 함수 포인터를 선언하는 방법

1. 반환값과 매개변수가 없는 함수

함수 포인터의 선언은 다음과 같이 이루어진다.

void (*함수포인터이름)();

예제)

#include <stdio.h>

void hello()
{
    printf("Hello, world!\n");
}

void from()
{
    printf("I'm from Korea.\n");
}

int main()
{
    void (*fptr)();

    fptr = hello;
    fptr();

    fptr = from;
    fptr();

    return 0;
}

--> void (*fptr)();을 통해 함수 포인터 fptr을 선언

--> hello 함수를 fptr에 저장해서 사용. (이때, hello()가 아닌 hello라는 것 주의!)

함수 포인터로 함수를 호출하기 위해서는 포인터에 ()를 붙이면 된다.

--> from 함수도 fptr에 저장해서 사용.

 

2. 반환값과 매겨변수가 있는 함수

반환값이나 매개변수가 존재할 경우에는 다음과 같이 선언한다.

반환자료형 (*함수포인터이름)(매개변수자료형1, 매개변수자료형2, ...);.

예제)

#include <stdio.h>

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

int sub(int a, int b)
{
    return a - b ;
}
int main()
{
    int (*fptr)(int, int);

    fptr = sum;
    printf("%d\n", fptr(20, 10));

    fptr = sub;
    printf("%d\n", fptr(20, 10));

    return 0;
}

--> int (*fptr)(int, int);를 통해 함수 포인터를 선언

--> fptr에 함수 이름을 저장해서 사용.

--> 함수 포인터를 호출하면서, 매개변수에 값을 넣어준다.

 

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

제일 간단한 이유는, 코드의 간결성 때문이다.

이를 보여주는 예시는 다음과 같다. 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void zero()
{
    printf("0 입니다.");
}
void one()
{
    printf("1 입니다.");
}
void two()
{
    printf("2 입니다.");
}
void three()
{
    printf("3 입니다.");
}

int main(void) {
    int sel;
    printf(" 0 ~ 3중에 골라주세요. \n");
    scanf("%d", &sel);
    switch (sel)
    {
    case 0:
        zero();
        break;
    case 1:
        one();
        break;
    case 2:
        two();
        break;
    case 3:
        three();
        break;
    }

    return 0;
}

이 긴 코드를 함수 포인터를 사용하면 다음과 같이 간결하게 줄일 수 있다.

int main(void) {
    int sel;
    printf(" 0 ~ 3중에 골라주세요. \n");
    scanf("%d", &sel);

    void (*fptr[4])() = { zero, one, two, three };
    fptr[sel]();


    return 0;
}

--> 여기서, *fptr[4]는 크기가 4인 1차원 배열을 의미한다.

2차원 배열의 경우, 괄호를 써준다. ex) (*fptr)[4]

 

  • 함수 포인터를 사용하면 CallBack 매커니즘을 구현할 때 함수를 또 다른 함수의 인자로 넘겨주기 위해 주로 사용된다. 소스코드에서 상호간에 함수명을 지정할 필요가 없는 자유를 제공한다.
  • 동적으로 늘어나거나, 줄어드는 UI에 이벤트 핸들러를 붙이거나 뗄 때, 이를 효율적으로 관리하기 위해 함수 포인터를 사용하면 간편하다.