본문 바로가기
컴퓨터/C & C++

[C++] 함수 포인터와 활용 예제

by HanJoohyun 2023. 8. 3.
반응형
반응형

안녕하세요. 한주현입니다. 오늘은 C++ 에서 함수 포인터 (function pointer) 에 대해 얘기해보겠습니다.

 

들어가며

변수는 값을 저장하는 메모리 공간의 이름,

포인터는 주소를 저장하는 메모리 공간의 이름 이듯이,

함수 포인터는 말 그대로 함수의 시작 주소를 저장하는 포인터입니다.

 

Pointer (포인터)

간단히 몸풀기로 우리가 익히 잘 알고 있는 pointer 부터 살펴보겠습니다.

 

#include <iostream>

int main()
{
    int num = 20;
    int *ptr = &num;
    std::cout << ptr << ": " << *ptr << std::endl;
    // 0x1000: 20
    return 0;
}

정수형 변수 num과 포인터 변수 ptr을 선언하여 num의 주소값을 포인터 변수 ptr에 저장하도록 하였습니다.

정수형 변수 num의 주소값을 저장하고 있는 ptr을 출력해보면 0x1000과 같이 나오게 되고, ptr을 dereference (역참조) 하게 되어 *ptr을 출력하게 되면 num에 저장된 값인 20이 출력되게 됩니다.

이를 그림으로 그려보면 아래와 같습니다.

 

Function Pointer (함수 포인터)

함수의 이름은 함수의 시작 주소입니다. 이를 함수 포인터 변수를 선언하여 할당하면 됩니다.

함수 포인터는 아래와 같이 함수의 반환 타입과 파라미터 목록으로 선언합니다.

예를 들어 반환 타입이 int 이고 파라미터로 int a, int b 를 받는 함수에서

int func(int a, int b)

이 함수의 함수 포인터 변수 ptr 은,

int (*ptr)(int, int)

로 선언할 수 있습니다.

 

코드로 살펴보면 아래와 같습니다.

 

#include <iostream>

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

int main()
{
    int (*ptr)(int, int);
    ptr = func;
    printf("%p\n", func);  // 0x2000
    printf("%p\n", ptr);   // 0x2000
    std::cout << func(2, 3) << std::endl;   // 함수 호출
    std::cout << ptr(2, 3) << std::endl;    // 포인터를 이용한 함수 호출
    std::cout << (*ptr)(2, 3) << std::endl; // 포인터를 이용한 함수 호출
    return 0;
}

위 포인터 그림과 마찬가지로 함수 포인터도 아래와 같이 표현해 볼 수 있습니다.

 

함수 포인터의 활용

  • for_each 구현

정수 배열에서 각각의 요소들을 전달된 함수 주소를 가지고 함수를 실행하는 프로그램을 만들어보겠습니다.

ForEach 함수는 배열에서 전달된 시작점과 끝점 주소와 이를 하나씩 수행할 함수 포인터를 전달받습니다.

전달받은 배열의 시작점과 끝점으로 배열의 각각 요소들은 전달받은 함수포인터가 가리키는 함수를 각각 수행하게 됩니다.

 

#include <iostream>

void ForEach(int *begin, int *end, void (*pf)(int)) {
    while (begin != end) {
        pf(*begin++);
    }
}

void Print1(int n) { std::cout << n << " "; }

void Print2(int n) { std::cout << n * n << " "; }

void Print3(int n) { std::cout << "Integer: " << n << std::endl; }

int main() {
    int arr[5] = {10, 20, 30, 40, 50};

    ForEach(arr, arr + 5, Print1); // 10 20 30 40 50
    std::cout << "\n\n";
    ForEach(arr, arr + 5, Print2); // 100 400 900 1600 2500
    std::cout << "\n\n";
    ForEach(arr, arr + 5, Print3);
    // Integer: 10
    // Integer: 20
    // Integer: 30
    // Integer: 40
    // Integer: 50
    return 0;
}

실제로 #include <algorithm> 에서 std::for_each 는 위에서 구현한 ForEach 함수와 동일한 기능을 수행합니다.

마치며

오늘은 예제 코드를 통해 함수 포인터에 대해 알아보았습니다.

여러분들께 도움이 되셨으면 좋겠습니다.

그럼 다음에 또 만나요!

 

반응형

댓글