C함수와 배열

함수 포인터와 콜백

함수 포인터 선언과 호출, typedef로 읽기 쉽게 만들기, qsort/bsearch 콜백 패턴, 함수 포인터 배열을 이용한 디스패치 테이블을 정리합니다.

마지막 수정 2026년 3월 26일

기본 패턴

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