본문 바로가기

BackEnd/C

함수 포인터(Function Pointer)

반응형

1. 함수 포인터란?


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


2. 함수의 이름이 제공하는 두 가지


  • 정의된 함수의 호출 

  • 수가 위치하고 있는 주소 값의 확인


함수도 실행이 되기 위해서는 컴파일이 완료된 형태로 메모리 공간에 저장이 되어야 한다. 


바로 이 위치 의 주소 정보를 얻을 수 있다는 뜻이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
 
void FuncOne(void)
{
    printf("FuncOne 함수가 호출되었다! \n");
}
 
void FuncTwo(void)
{
    printf("FuncTwo 함수가 호출되었다! \n");
}
 
 
int main(void)
{
    FuncOne();
    FuncTwo();
 
    printf("FuncOne의 주소 값: %#x \n", FuncOne);
    printf("FuncTwo의 주소 값: %#x \n", FuncTwo);
 
    return 0;
}

cs


1
2
3
4
FuncOne 함수가 호출되었다!
FuncTwo 함수가 호출되었다!
FuncOne의 주소 값: 0x401530
FuncTwo의 주소 값: 0x40154b
cs


16~17행 : 일반적인 함수 호출을 보여준다. 이처럼 함수의 이름과 소괄호를 이어주면, 이는 해당 함 수를 호출하겠다는 의미가 된다


19~20행: 소괄호 없이 함수의 이름만 사용이 되면, 이는 해당 함수가 저장되어 있는 메모리의 주소 값을 의미하게 된다. 


3. 함수의 주소 값을 저장하는 포인터 변수의 선언


함수가 저장되어 있는 메모리의 주소 값을 저장하기 위한 포인터 변수를 가리켜 함수 포인터 변수라 한다.


int FuncName(int arg) { // 이와 같은 형태로 함수가 정의되었다고 가정 하자


}


이 때 이 함수의 주소 값을 저장할 수 있는 포인터 변수는 다음과 같은 형태로 선언해야 한다.


int (* funcPtr) (int arg);


함수 포인터에도 형이 존재한다. 참조할 함수의 반환형과 매개변수 형을 모두 명시하고,변수의 


이름 앞에 * 기호를 붙여서 선언하는 것이 포인터 변수임을 명시해야 한다.


포인터 형 정보는 메모리 접근을 위해 필요하듯이, 함수 포인터 형 정보는 함수 호출을 위해 필요하다.



이렇게 선언이 된 함수 포인터 변수는 반환형이 int이고 하나의 int형 매개변수를 갖는 함수의 주


소값이 라면 무엇이든지 저장 가능하다.


funcPtr=FuncName; 


함수의 이름이 주소값을 의미하므로 단순한 대입연산으로 저장이 가능하다.


참고로 함수 포인터 변수의 선언시에는 매개변수의 형만 명시해도 된다.


int (*funcPtr)(int);



4. 함수 포인터 변수를 이용해서도 함수를 호출할 수 있다


함수 포인터를 선언할 때 반환형과 매개변수 형을 일치시켜줘야 하는 이유는, 함수 포인터를 이용


해서 해당 함수의 호출을 가능하도록 하기 위함이다(이 두 가지는 함수 호출에 있어서 필요한 최소

의 정보이다).


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
 
int SimpleAddOne(int num)
{
    return num+1;
}
 
int AddTwoNumber(int n1, int n2)
{
    return n1+n2;
}
 
 
int main(void)
{
    int (*fctPtrOne)(int);
    int (*fctPtrTwo)(intint);
 
    fctPtrOne=SimpleAddOne;
    fctPtrTwo=AddTwoNumber;
 
    printf("10+1=%d \n", fctPtrOne(10));
    printf("10+20=%d \n\n", fctPtrTwo(1020));
 
    printf("10+1=%d \n", (*fctPtrOne)(10));
    printf("10+20=%d \n\n", (*fctPtrTwo)(1020));
 
    return 0;
}


cs


1
2
3
4
5
10+1=11
10+20=30
 
10+1=11
10+20=30
cs


22~23행: 함수 포인터를 이용해서 함수를 호출하고 있다. 이처럼 함수 포인터는 함수의 이름처럼 활용할 수 있다.


25~26행: 일반적으로 포인터가 가리키는 대상을 참조할 때에는 * 연산자를 활용해야 한다고 생각 한다. 따라서 함수 포인터가 가리키는 대상 함수를 호출하는 과정에서 * 연산자를 활용하는 것도 허용이 된다.



5.  함수 포인터를 반환하는 함수의 정의


아래 그램에서 함수 포인터의 반환형을 어떻게 채워야 할까?



GoodStruct 함수의 주소 값을 저장할 수 있는 함수 포인터는 다음과 같이 선언하면 된다.


 int (* fctPtr) (void);

바로 이 fctPtr의 함수포인터 형을 함수의 반환형으로 선언해야한다.


위 선언에서 fctPtr이라는 변수 이름을 빼 보자. 그러면 남는 것은 다음과 같다.

 

 int (*) (void);


그리고 이를 C언어의 표준에서는 다음과 같은 형태로 채워 넣을 것을 요구하고 있다.





6.  typedef 선언과 함수 포인터를 반환하는 함수의 정의


 typedef 선언을 이용하면 함수 포인터를 반환하는 함수의 정의를 간단하게 해결한다.









반응형