포스트

함수포인터

C언어

함수포인터

함수포인터

장점 : 콜백 함수 (callback function) 구현 콜백함수 : 특정 작업 완료 후, 실행될 함수를 동적으로 지정 , 개발간 권한 위임 (분리된 독립적 개발)


Struct 안에 함수 포인터 -> 마치 객체처럼

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
#include <stdio.h>

int add(int x, int y) {
	return (x + y);
}

typedef struct _calculator_t {
	int (*op)(int a, int b);
} calculator_t;
typedef int (*fp_calc)(int, int);


int main() {
	calculator_t calculator;
	calculator.op = &add;

	int a = 7;
	int b = 3;
	float r = 0;

	r = calculator.op(a, b);

	printf("%d%c%d=%3.1f\n", a, '+', b, (float)r);

	return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>

int hot(int a, int b) {
	printf("%s ", __func__);	// __func__ : 매크로, 함수 이름을 문자열로
	printf("(a,b) = (%d, %d)\n", a, b);
	return (a + b);
}
void set_hot(int a, int b, int(*func)(int, int)) {
	int res = func(a, b);
	printf("res : %d\n", res);
}
int main() {

	set_hot(1, 2, hot);

	return 0;
}


2차원 함수 포인터

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
#include <stdio.h>

#define COL (2)
#define ROW (2)

void f00() { printf("This function is %s()", __FUNCTION__); }
void f01() { printf("This function is %s()", __FUNCTION__); }
void f10() { printf("This function is %s()", __FUNCTION__); }
void f11() { printf("This function is %s()", __FUNCTION__); }

int main() {
	// 2차원 함수 포인터 배열을 선언하시오.
	void (*fp[COL][ROW])() = { NULL, };

	// 2차원 함수 포인터 배열에 위 함수를 모두 대입하시오
	fp[0][0] = &f00;
	fp[0][1] = &f01;
	fp[1][0] = &f10;
	fp[1][1] = &f11;

	int col = 0;
	int row = 0;
	printf("input col : ");
	int d1 = scanf("%d", &col);
	printf("input row : ");
	int d2 = scanf("%d", &row);

	// 2차원 함수 포인터배열의 주소 출력 및 함수를 호출하시오
	printf("Address of fp[%d][%d]: 0x%p \r\n", col, row, fp[col][row]);
	fp[col][row]();
	printf("\r\n");

	return 0;
}


함수 포인터 이럴 때 쓰면 좋다

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
#include<stdio.h>

#define print_func_name (printf("%s\n", __func__))

void zero() { print_func_name; }
void one() { print_func_name; }
void two() { print_func_name; }
void three() { print_func_name; }
void four() { print_func_name; }
void five() { print_func_name; }
void six() { print_func_name; }
void seven() { print_func_name; }
void eight() { print_func_name; }
void nine() { print_func_name; }

int main() {
	int num = 0;
	printf("Enter a num between 0 to 9 : ");
	scanf("%d", &num);


#define MAX_FUNC_CNT (10)
	
	void (*fp_arr[MAX_FUNC_CNT])() = {
		zero, one, two, three, four, five, six, seven, eight, nine
	};


	(*fp_arr[num])();


	return 0;
}


더 많은 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

// 콜백 함수의 형태로 사용할 함수
void print_result(int result) {
    printf("Result: %d\n", result);
}

// 함수를 포인터로 받아서 호출하는 함수
void perform_calculation(int a, int b, void (*callback)(int)) {
    int result = a + b;  // 계산 작업
    callback(result);     // 계산 완료 후 콜백 함수 호출
}

int main() {
    // perform_calculation 함수에 콜백 함수 print_result를 전달
    perform_calculation(5, 3, print_result);
    
    return 0;
}

예시

void (*pfunc)(int, int) = &bts;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

void bts(int a, int b) {
    printf("hi");
}
int main(){
    int a = 123;
    void (*pfunc)(int, int) = &bts;   // ==  void (*pfunc)(int, int) = (void*)bts;
    pfunc(1,3);

   
    return 0;
}

int (*operation)(int, int);

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>

// 함수 선언
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int multiply(int a, int b) {
    return a * b;
}

int divide(int a, int b) {
    if (b != 0) {
        return a / b;
    }
    else {
        printf("Error: Division by zero\n");
        return 0;
    }
}

int main() {
    // 함수 포인터 선언
    int (*operation)(int, int); //괄호 중요

    int num1 = 10, num2 = 5;
    char operator = '+';

    // operator에 따라 다른 함수를 호출하도록 설정
    if (operator == '+') {
        operation = add;
    }
    else if (operator == '-') {
        operation = subtract;
    }
    else if (operator == '*') {
        operation = multiply;
    }
    else if (operator == '/') {
        operation = divide;
    }
    else {
        printf("Invalid operator\n");
        return -1;
    }

    // 함수 포인터를 통해 함수 호출
    int result = operation(num1, num2);
    printf("Result: %d\n", result);

    return 0;
}


void* op = (void*)add;

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>

// int형 값을 반환하는 함수
int add(int a, int b) {
    return a + b;
}

// void형 함수: int형 함수를 받는 함수
void callOperation(void* op, int a, int b) {
    // void* 포인터를 (int (*)(int, int)) 형식으로 캐스팅
    int (*operation)(int, int) = (int (*)(int, int))op;
    printf("Result: %d\n", operation(a, b));
}

int main() {
    // add 함수의 주소를 void* 포인터로 넘기기
    void* op = (void*)add;
    
    // callOperation 함수에서 void* 포인터를 사용하여 add 함수 호출
    callOperation(op, 5, 3);  // Result: 8 출력

    return 0;
}


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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <stdio.h>
#include<conio.h>

typedef enum {
    UP,
    DOWN,
    LEFT,
    RIGHT,
    EVENT_CNT   //EventType의 총 개수 및 유효성 확인 위해
} EventType;

// 콜백 함수 타입 정의
typedef void (*EventHandler)(void); //반환 void, 인자 void, 함수 포인터 타입 정의

typedef struct {
    EventHandler handlers[EVENT_CNT];
}EventSystem;

void register_event_handler(EventSystem* system, EventType type, EventHandler handler) {
    if (type < EVENT_CNT) {
        system->handlers[type] = handler;
    }
}
void trigger_event(EventSystem* system, EventType type) {
    if (type < EVENT_CNT && system->handlers[type]) {
        system->handlers[type]();
    }
}

// 콜백 함수의 등록
//void button_click(ButtonCallback callback) {
void up_button_press(void (*callback)(void)) {
    //printf("up 버튼이 클릭되었습니다.\n");
    callback(); // 콜백 함수 호출
}

void down_button_press(void (*callback)(void)) {
    //printf("down 버튼이 클릭되었습니다.\n");
    callback(); // 콜백 함수 호출
}
void left_button_press(void (*callback)(void)) {
    //printf("down 버튼이 클릭되었습니다.\n");
    callback(); // 콜백 함수 호출
}void right_button_press(void (*callback)(void)) {
    //printf("down 버튼이 클릭되었습니다.\n");
    callback(); // 콜백 함수 호출
}
// 버튼이 눌렸을때 실제 동작 함수
void up_button_pressed() {
    printf("이벤트: up 버튼 클릭 처리가 완료되었습니다.\n");
}

void down_button_pressed() {
    printf("이벤트: down 버튼 클릭 처리가 완료되었습니다.\n");
}
void left_button_pressed() {
    printf("이벤트: left 버튼 클릭 처리가 완료되었습니다.\n");
}
void right_button_pressed() {
    printf("이벤트: right 버튼 클릭 처리가 완료되었습니다.\n");
}

void num_handler(int n) {

}
int main() {
    
    EventSystem system = { 0 };
    register_event_handler(&system, UP, up_button_pressed);
    register_event_handler(&system, DOWN, down_button_pressed);
    register_event_handler(&system, LEFT, left_button_pressed);
    register_event_handler(&system, RIGHT, right_button_pressed);

    trigger_event(&system, UP);
    trigger_event(&system, DOWN);
    trigger_event(&system, LEFT);
    trigger_event(&system, RIGHT);

    /*
    up_button_press(&up_button_pressed); // up 버튼 클릭 이벤트 등록
    down_button_press(&down_button_pressed);
    left_button_press(&left_button_pressed);
    right_button_press(&right_button_pressed);
    */

    char n = getch();
    printf("%c", n);
    //scanf("%d", &n);



    return 0;
}


함수 포인터의 무수한 활용

: 코드를 나눠서 짤 수 있음 -> 독립적 개발

```c, main.c //#include #include"tetris.h"

int main() { // 이벤트 시스템 초기화 EventSystem system = { 0 };

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
// 이벤트 핸들러 등록
register_event_handler(&system, GAME_INIT, tetris_game_init);
register_event_handler(&system, GAME_START, tetris_game_start);
register_event_handler(&system, GAME_OVER, tetris_game_over);

register_event_handler(&system, KEY_UP, tetris_key_up);
register_event_handler(&system, KEY_DOWN, tetris_key_down);
register_event_handler(&system, KEY_LEFT, tetris_key_left);
register_event_handler(&system, KEY_RIGHT, tetris_key_right);
register_event_handler(&system, KEY_FIRE, tetris_key_fire);
register_event_handler(&system, KEY_BOMB, tetris_key_bomb);

// 게임 시작
trigger_event(&system, GAME_INIT);
trigger_event(&system, GAME_START);

// 키 입력 시뮬레이션
trigger_event(&system, KEY_UP);
trigger_event(&system, KEY_DOWN);
trigger_event(&system, KEY_LEFT);
trigger_event(&system, KEY_RIGHT);
trigger_event(&system, KEY_FIRE);
trigger_event(&system, KEY_BOMB);

// 게임 종료
trigger_event(&system, GAME_OVER);

return 0; }
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
36
37
38
39
40
41
42
43
44
45
<br>

```c, tetris.h
#ifndef __TETRIS_H__
#define __TETRIS_H__

#include <stdio.h>

// 이벤트 타입 정의
typedef enum {
    KEY_UP,
    KEY_DOWN,
    KEY_LEFT,
    KEY_RIGHT,
    KEY_FIRE,
    KEY_BOMB,
    GAME_INIT,
    GAME_START,
    GAME_OVER,
    EVENT_COUNT  // 총 이벤트 개수
} EventType;

// 콜백 함수 타입 정의
typedef void (*EventHandler)(void);

// 이벤트 시스템 구조체
typedef struct {
    EventHandler handlers[EVENT_COUNT];
} EventSystem;

void tetris_game_init(void);
void tetris_game_start(void);
void tetris_game_over(void);

void tetris_key_up(void);
void tetris_key_down(void);
void tetris_key_left(void);
void tetris_key_right(void);
void tetris_key_fire(void);
void tetris_key_bomb(void);

#endif



```c, tetris.c #include “tetris.h”

// 이벤트 등록 함수 void register_event_handler(EventSystem* system, EventType type, EventHandler handler) { if (type < EVENT_COUNT) { system->handlers[type] = handler; } }

// 이벤트 트리거 함수 void trigger_event(EventSystem* system, EventType type) { if (type < EVENT_COUNT && system->handlers[type]) { system->handlerstype; } }

void tetris_game_init(void) { printf(“tetris initialized.\n”); }

void tetris_game_start(void) { printf(“tetris started.\n”); }

void tetris_game_over(void) { printf(“tetris game over…\n”); }

void tetris_key_up(void) { printf(“tetris up\n”); }

void tetris_key_down(void) { printf(“tetris down\n”); }

void tetris_key_left(void) { printf(“tetris left\n”); }

void tetris_key_right(void) { printf(“tetris right\n”); }

void tetris_key_fire(void) { printf(“tetris fire\n”); }

void tetris_key_bomb(void) { printf(“tetris booom !!!\n”); }

```