기본 패턴
c
// 선언: 반환타입 (*이름)(매개변수 타입들)
int (*op)(int, int);
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
op = add;
printf("%d\n", op(3, 4)); // 7
op = mul;
printf("%d\n", op(3, 4)); // 12설명
typedef로 가독성 향상
함수 포인터 타입은 복잡하므로 typedef를 사용하면 훨씬 읽기 쉬워집니다.
c
// typedef 없이
int (*callback)(int, int);
// typedef 사용
typedef int (*BinaryOp)(int, int);
BinaryOp op = add;
// 반환값이 포인터인 경우
typedef char *(*Formatter)(int);qsort — 함수 포인터 콜백의 대표 예
c
#include <stdlib.h>
// 비교 함수: 음수=a가 앞, 0=같음, 양수=b가 앞
int cmpInt(const void *a, const void *b) {
int ia = *(const int *)a;
int ib = *(const int *)b;
return (ia > ib) - (ia < ib); // 오버플로우 없는 비교 관용구
}
int arr[] = {5, 2, 8, 1, 9};
qsort(arr, 5, sizeof(int), cmpInt);
// arr = {1, 2, 5, 8, 9}bsearch — 이진 탐색 콜백
c
int key = 5;
int *found = bsearch(&key, arr, 5, sizeof(int), cmpInt);
if (found) printf("found: %d\n", *found);콜백 함수 패턴
c
typedef void (*Logger)(const char *msg);
void logToStdout(const char *msg) { printf("[LOG] %s\n", msg); }
void logSilent(const char *msg) { (void)msg; /* 아무것도 안 함 */ }
void processData(int *data, int n, Logger log) {
for (int i = 0; i < n; i++) {
if (data[i] < 0) log("negative value found");
}
}
// 런타임에 동작을 교체 가능
processData(arr, n, logToStdout);
processData(arr, n, logSilent);함수 포인터 배열 — 디스패치 테이블
c
typedef int (*Op)(int, int);
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
Op dispatch[] = {add, sub, mul}; // 배열로 묶기
int opcode = 1; // sub
printf("%d\n", dispatch[opcode](10, 3)); // 7
// if/switch 없이 동작 선택 가능빠른 정리
| 문법 | 설명 |
|---|---|
int (*fp)(int, int) | 함수 포인터 선언 |
fp = funcName | 함수 주소 할당 (& 생략 가능) |
fp(a, b) | 함수 포인터 호출 |
typedef int (*Op)(int, int) | 함수 포인터 타입에 별칭 부여 |
qsort(arr, n, size, cmp) | 비교 함수를 콜백으로 받는 정렬 |
bsearch(&key, arr, n, size, cmp) | 정렬된 배열에서 이진 탐색 |
| 디스패치 테이블 | 함수 포인터 배열로 분기 대체 |
주의할 점
qsort 비교 함수에서 return *(int*)a - *(int*)b 는 정수 오버플로우를 일으킬 수 있습니다. 큰 양수와 큰 음수를 비교할 때 결과가 뒤집힐 수 있으므로, (a > b) - (a < b) 관용구를 사용하세요.
함수 포인터는 NULL일 수 있습니다. 호출 전에 반드시 확인하세요: if (fp) fp(args);
참고 링크
1 sources