본 글은 공부용으로 작성된 게시글입니다.
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 |
댓글