본문 바로가기
프로그래밍/C++

함수포인터

by Nessie! 2022. 8. 25.
본 글은 공부용으로 작성된 게시글입니다.

C++에는 포인터가 있다.

간단하게 설명하면 포인터는 메모리 주소를 저장하여 그 주소를 기준으로 그 위치를 가리키는 역할을 한다.

 

함수 또한 마찬가지로 메모리에 저장이되니 본인의 주소가 있을 것이다.

이를 포인터형식으로 저장하는 것이 함수포인터라고 한다.

 

즉, 함수의 주소값을 저장하는 변수이다.

 

쉽게말하면 그렇다고한다.

 

좀 더 자세히 설명한 내용을 보면, 

함수의 이름은 메모리에 올라간 함수의 시작 주소를 가리키는 포인터 상수(constant pointer)라고 부른다.

이 포인터 상수(constant pointer)는 포인터 변수가 가리키고 있는 주소 값을 변경할 수 없는 포인터라고한다... ㅎ;

 

이렇게 함수의 시작 주소를 가리키는 포인터 상수를 함수 포인터(function pointer)라고 부른다.

그리고 함수는 고유한 l-value 함수 타입이라고한다.

 

 

그렇다면 함수포인터 변수는 어떻게 사용할까?

함수 포인터의 포인터 타입은 함수의 반환값과 매개변수에 의해 결정된다.

즉 함수의 원형을 알아야만 해당 함수에 맞는 함수 포인터를 만들 수 있으니 작성 시 동일한 반환형, 매개변수를 작성하자

 

비 상수 함수 포인터(non-const function pointer) 생성하는 문법
int (*fcnPtr)();

int (*fp)(int, int);
반환타입 / 변수이름 / 매개변수 순이다.

 

아래 함수의 함수포인터를 작성하고자한다면

void Func(int, int); 

이렇게 작성할 수 있다. 

void (*ptr_func)(int, int);

이때, 작성 시 주의해야할 점은 연산자 우선순위를 고려하여 ()를 사용해줘야한다는 점이다.

 

 

근데, 함수는 그냥 부르면 땡 아닌가? 도대체 왜 쓰는걸까? 싶을 수 있다.

(그게 나다 ㅜㅜ)

찾아보니 함수 포인터는 함수를 또 다른 함수의 인수로 전달할 때 유용하게 사용된다고 한다.

 

인수와 매개변수의 차이가 뭔지 모르는 사람은 아래 접은글을 보자!

더보기

Parameter(매개변수), Argument(인수, 인자)
함수를 정의할 때 사용되는 변수를 매개변수, 실제로 함수가 호출될 때 넘기는 변수값을 인자라고 함

 

즉, 함수를 실행한 결과값을 다른 함수에 넘겨주는 상황에서 유용해서 사용된다고 한다! 

이런식으로 다른 함수의 인자값으로 쓰이는 함수를 콜백함수라 부른다고한다고한다고한다~

 

 

기본적으로 위의 문법으로 작성할 수 있으나, 보기 넘 구리다!!! 그리고 복잡해서 쓰기에도 구리다!!!!

그래서 다르게 작성하는 방법도 있다.

 

위의 복잡한 표기법을 단순화하는 방법으로는 다음의 두 가지 키워드를 사용할 수 있다.

1. typedef 키워드

typedef 키워드를 이용하면 복잡한 함수 포인터형에 새로운 이름을 붙여서 사용할 수 있다.

구조체를 선언하는 것과 비슷하다.

typedef double (*CalcFunc)(double, double); // 함수 포인터에 calcFunc이라는 새로운 이름을 붙임.
CalcFunc ptr_func = calc;

근데 실제로 typedef 키워드를 통해 간결하게 구조체를 정의할 수도 있다보니 진짜 비슷하게 쓰인다고 봐도 될 것 같다...?

 

2. auto 키워드

auto 키워드를 이용하면 함수 포인터형으로 자동 타입 변환된다. 세상 좋다

auto ptr_func = calc;

 

하지만 어느상황에서든 auto 키워드를 사용할때에는 주의가 필요하다.

상황이 모호할 때 사용하게되면 필요한 타입이 아닌 다른 타입으로 잘못 변환되는 경우가 존재할 수 있기 때문이다! 조심!

 

더보기

아래 적혀있는 내용은 하기 기재한 게시글을 참고하여 개인적으로 공부를 한 내용인데,  나중에 공부할떄 다시 보면 도움이 될까 싶어 접은글로 남겨둔다

개인적인 생각을 메모해두었기 때문에 틀린 헛소리일 확률이 높다...

https://hwan-shell.tistory.com/87

 

매개변수로 함수 포인터를 전달 받는 방법

void fnc_1() {
    printf("fnc 함수\n");
}

void fnc_2(int n) {
    printf("%d\n", n);
}

void fnc_print(void(*fnc)()) {
    fnc();
}

void fnc_print2(void(*fnc)(int), int n) {
    fnc(n);
}

int main(void) {

    fnc_print(fnc_1);
    fnc_print2(fnc_2, 5);

    return 0;
}

=================

변수로 선언하여 접근하는 방법

int main(void) {

    void(*fp_1)();
    void(*fp_2)(int);

    fnc_print(fp_1);
    fnc_print2(fp_2, 5);

    return 0;
}

ㄴ 선언한 함수포인터형 변수에 함수를 저장하는 부분이 없는데 어떻게 문제 없이 실행되는 것인지 잘 모르겠따
ㄴ 관련하여 코드를 그대로 실행시켜보았더니 초기화되지 않은 변수를 사용한다는 오류가 발생했다!
ㄴ 작성자가 오타를 낸 것 같다.

void(*fp_1)() = fnc_1;
void(*fp_2)(int) = fnc_2;
으로 변경하여 실행하니 원하는 결과값으로 잘 실행되었다.


typedef를 통해 선언하여 사용하는 방법
typedef void(*Fn_1)();
typedef void(*Fn_2)(int);

으로 선언하여 main 함수에서 아래와 같이 작성하여 사용한다.
Fn_1 fp_1;
Fn_2 fp_2;

=> 이 코드 전문을 실행하면 오류가 발생함.
아무래도 사용법이 잘못된 것 같다.

'프로그래밍 > C++' 카테고리의 다른 글

[C++] STL Deque 컨테이너  (0) 2022.10.25
비트연산자  (1) 2022.09.05
Lvalue Rvalue  (0) 2022.08.23
복사생성  (0) 2022.08.23
가상함수테이블  (0) 2022.08.22

댓글