C 기본 문법 – 함수 – 3 – 함수 포인터

C 기본 문법 – 함수 – 3편: 함수 포인터 완전 정복

여러분 안녕하세요! 😊
오늘은 C 언어에서 한 단계 더 발전된 개념인 **함수 포인터(Function Pointer)**에 대해 공부해보겠습니다.

🧠 함수 포인터란?
말 그대로 함수의 주소를 저장하고, 그 주소를 통해 함수를 호출할 수 있게 해주는 포인터예요.
마치 “전화번호부”처럼, 전화번호(주소)를 통해 사람(함수)에 연결하는 방식이죠!

“함수를 변수처럼 다룬다고?”
“함수를 포인터로 전달한다고?”
처음엔 어렵게 느껴질 수 있지만, 비유와 예시를 통해 차근차근 풀어드릴게요!


1. 함수 포인터란 무엇인가요?

일반 포인터는 메모리 주소를 저장하는 변수죠?
함수 포인터는 그 중에서도 함수의 시작 주소를 저장하는 특별한 포인터입니다.

int add(int a, int b) {
    return a + b;
}

위 함수는 메모리에 저장되고, 시작 주소가 존재해요.
이 주소를 변수처럼 저장해서 나중에 호출할 수 있습니다.


2. 함수 포인터 선언 방법

반환형 (*포인터이름)(매개변수목록);

예를 들어 int add(int, int)를 가리키는 함수 포인터는 다음과 같이 선언합니다:

int (*fp)(int, int);

*fp는 함수의 주소를 저장하고
(int, int)는 함수의 매개변수 목록입니다.


3. 함수 포인터 사용 예제

기본 함수

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

함수 포인터 선언 및 사용

int (*funcPtr)(int, int);  // 함수 포인터 선언
funcPtr = multiply;        // 주소 저장
int result = funcPtr(4, 5);  // 포인터를 통해 함수 호출
printf("곱셈 결과: %d
", result);  // 출력: 20

🎯 funcPtr(4, 5)multiply(4, 5)와 같은 효과입니다!


4. 함수 포인터와 배열

함수 포인터를 배열 형태로 선언하면, 다양한 함수를 선택적으로 호출할 수 있어요!

예시: 간단한 계산기

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; }
int divide(int a, int b) { return a / b; }
int (*ops[4])(int, int) = { add, sub, mul, divide };

int main() {
    int x = 20, y = 5;

    printf("덧셈: %d
", ops[0](x, y));  // add
    printf("뺄셈: %d
", ops[1](x, y));  // sub
    printf("곱셈: %d
", ops[2](x, y));  // mul
    printf("나눗셈: %d
", ops[3](x, y));  // divide

    return 0;
}

🎯 배열을 이용하면 함수 호출을 동적으로 선택할 수 있어요!


5. 함수 포인터를 인자로 전달하기

함수를 다른 함수에 인자로 넘길 수 있다면 어떨까요?
바로 그게 함수 포인터의 강력한 기능입니다!

예제: 연산자 전달 함수

int compute(int a, int b, int (*op)(int, int)) {
    return op(a, b);
}

int add(int x, int y) { return x + y; }
int mul(int x, int y) { return x * y; }
int main() {
    printf("5 + 3 = %d
", compute(5, 3, add));
    printf("5 * 3 = %d
", compute(5, 3, mul));
    return 0;
}

🎯 마치 “전략 전달”처럼 원하는 기능을 넘겨줄 수 있어요!


6. typedef로 함수 포인터를 간단하게

함수 포인터 문법은 헷갈리기 쉬워요.
그래서 **typedef를 이용해서 별칭(alias)**을 만들면 훨씬 읽기 쉽습니다!

예제

typedef int (*CalcFunc)(int, int);

int sub(int a, int b) {
    return a - b;
}
int main() {
    CalcFunc func = sub;
    printf("10 - 4 = %d
", func(10, 4));
    return 0;
}

7. 함수 포인터와 콜백 함수

함수 포인터는 콜백(callback) 함수 개념과 매우 밀접합니다.
콜백 함수란, 특정 이벤트가 발생했을 때 미리 등록된 함수를 호출하는 방식입니다.

예제: 문자열 처리 콜백

void runCallback(void (*callback)()) {
    printf("작업 시작
");
    callback();
    printf("작업 종료
");
}

void sayHello() {
    printf("안녕하세요!
");
}

int main() {
    runCallback(sayHello);  // sayHello를 콜백으로 전달
    return 0;
}

🎯 GUI 이벤트, 타이머 처리, 정렬 기준 함수 등에서 자주 활용됩니다!


✅ 함수 포인터 요약표

문법 요소 예시 설명
함수 포인터 선언 int (*fp)(int, int); int 반환, int 2개 받는 함수
함수 주소 저장 fp = add; 함수 이름만 써도 주소 저장
함수 호출 fp(3, 4); add(3, 4);와 동일
함수 포인터 배열 fp[4] 다양한 함수 담기
함수 인자로 전달 compute(a, b, add); 동적 기능 처리 가능
typedef 사용 typedef int (*FUNC)(int, int); 코드 가독성 향상

⚠️ 함수 포인터 사용 시 주의사항

주의사항 설명
매개변수와 반환형 정확히 일치해야 함 예: int (*f)(int, int) 형태의 함수만 할당 가능
null 포인터 체크 필수 잘못된 주소 접근은 프로그램 다운
함수 이름만으로 주소 전달됨 &add 대신 add만 써도 OK
문법이 복잡하므로 typedef 적극 활용 가독성을 높이기 위해 typedef 사용 권장

마무리하며 💬

함수 포인터는 C 언어에서 고급 기능에 속하지만,
이 개념을 잘 활용하면 더 유연하고 구조적인 프로그램을 만들 수 있어요!

🎯 마치 “리모컨”처럼, 어떤 함수든 버튼 하나로 호출할 수 있는 방식!
전자제품처럼 모듈화된 기능을 함수 포인터로 조립해보세요 🔧

다음 편에서는 함수 포인터를 활용한 정렬 기준 함수 전달이나
메모리 관련 고급 활용도 다뤄볼게요.

궁금한 부분이 있다면 언제든지 질문 주세요!
C 언어 마스터까지, 함께 달려봅시다! 💻🔥

답글 남기기