삽질의 현장/- C

곱씹어보자 C!_#025_삽잡이의 두서없이 막말하는 함수 포인터

shovelman 2015. 6. 30. 22:43

달립니다 달립시다~~

삽잡이는 달립니다~~ 

이번 시간에는 함수포인터로 C부려봅시다~~


함수 포인터... 많이 사용됩니다. 크게 사용하는 분야를 2개로 나눌 수 있습니다.


첫번째, 프로그램 기능의 유연성을 키우고자 할때,

두번재, Callback 함수를 만들어 낼 때 입니다.


첫번째에 대한 설명을 드리자면,

함수포인터 하나만 가지고 있으면 함수의 주소 즉, 이름을 대입하여 많은 곳에 사용할 수 있게 됩니다.

즉, 어떨 때는 A함수, 어떨 때는 B함수 코드 한줄 안고치고도 기능이 바뀔 수 있죠...

이게 바로 유연성을 키운다고 말하는 것입니다.

단, 같은 시그니처를 가지고 있을 때 사용할 수 있겠죠...

이렇게 사용할 수 있습니다...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
//Add, Sub 함수 이름만 다르고 두 시그니처는 같군...
int Add(int a, int b)
{
    return a+b;
}
 
int Sub(int a, int b)
{
    return a-b;
}
 
void main()
{    
    int (*pf)(intint);
    
    // 이것만 바꿀 수 있게 한다면.... 편하게 막 가져다 쓸 수 있군.
    pf = Add;
    //pf = Sub;
 
    //Add가 될 수도 Sub가 될 수 도...
    printf("%d\n", pf(10,20));
    printf("%d\n", pf(10,20));
}
cs


다음, 함수포인트가 사용되는 분야 두번째는

바로 Callback 함수를 사용할 때입니다.


자... 여러분 생각해봅시다...

우리가 만드는 main함수는 print함수 scanf함수 등등 불러쓰죠...

이것을 바로 클라이언트인 우리가 서버로부터 해당 함수를 Call 한다고 합니다.


그럼 callback은 뭘까요? 

반대로 서버에서 클라이언트의 기능인 함수를 호출하는 것입니다...

한번 보실까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
//////////////////////////////////////////Server
void Client();
void Server(int data)
{
    printf("server : %d\n", data);
    
    //Callback
    Client();
}
 
/////////////////////////////////////////Client
 
void Client()
{
    printf("I'm Client!\n");
}
void main()
{
    Server(100);
}
cs


자... Callback 입니다. 보이십니까?

Server 영역인 Server 함수에서 Client 영역에 있는 Client 함수를 호출하죠...

이런게 콜백입니다.

그럼 여기까지!

...


라고 할줄 알았죠?? 문제가 있습니다... 뭘까요?

클라이언트인 main 보다 Server 함수 즉, 우리가 요청 하고자하는... 

기존에 만들어져 있던 함수들이 늦게 만들어졌을까요?

그러니까 이전에 만들어졌던 함수가 어떻게 신생아인 우리 클라이언트쪽의 함수의

이름을 알고 Callback 할 수 있냐 이 말입니다...


존재하지도 않는 함수를 호출한다는... 이런 어메이징한....

안되요 이건!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
//////////////////////////////////////////Server
void Server(int data, void (*pf)())
{
    printf("server : %d\n", data);
    pf();
}
 
/////////////////////////////////////////Client
 
void Client()
{
    printf("I'm Client!\n");
}
void main()
{
    Server(100, Client);
}
cs


자... 이건 어떤가요?

Server 단에는 Client측의 함수를 찾아볼 수 있나요? 없죠?

함수포인트 하나를 매개변수로 받고 있네요...

이러면 미리 만들 수 있겠어요!


그리고 Client 측에서 이렇게 말하는 것이죠...

"야 서버... 너 기능 수행하면서 어떤일 생기거나 나한테 물어보고 싶은거 있으면 이거 수행해라"


이런다는는거죠!!! 그말을 어디서 하느냐... 

바로 main 함수에서 한다 이겁니다... 그렇게 요청을 하고 있어요...


이렇게 하면 Callback을 이용해서 Client의 정책을 서버에 반영시킬 수 있다 이겁니다.

서버에 심는다... 반영시킨다...

이게 Callback입니다...


마지막 Callback 예시를 살펴보시고~

마치도록 하겠습니다!


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
31
32
33
34
35
#include <stdio.h>
void PrintArray(int list[], int size)
{
    int i;
    for(i = 0; i< size++i)
        printf("%5d" , list[i]);
    printf("\n");
}
int Find(int list[], int sizeint (*pf)(int))
{
    int i;
    for ( i = 0; i < size++i)
        //니가 찾고자 하는 값이더냐?
        if( pf(list[i]) )
            return i;
 
    return -1;
}
///////////////////////////////////////////////client
void pred(int data)
{
    return 30 < data && (data%5== 0;
}
void main()
{
    int list[10= {5,73,8,90,20,57,89,21,43,67};
    int size = 10;
 
    PrintArray(list, size);
    {
        int idx = Find(list, size, pred);
        if(0<=idx)
            printf("%d: %d\n", idx, list[idx]);
    }
}
cs