티스토리 뷰

반응형

C언어 기초 Chapter 19: 함수 포인터와 void 포인터


19-1. 함수 포인터와 void 포인터

함수 포인터란?

  • 함수의 주소를 저장하는 포인터 변수
  • 함수도 메모리에 올라가기 때문에 시작 주소가 존재
  • 이를 이용해 함수를 변수처럼 전달하거나 동적으로 호출할 수 있음

기본 문법

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

예제: 함수 포인터 선언과 사용

#include <stdio.h>

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

int main(void) {
    int (*fp)(int, int);   // 함수 포인터 선언
    fp = add;              // 함수 주소 저장

    int result = fp(3, 4); // 함수 포인터로 호출
    printf("결과 = %d\n", result);
    return 0;
}

👉 출력: 결과 = 7


함수 포인터를 인자로 전달

#include <stdio.h>

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

void calc(int (*op)(int, int), int x, int y) {
    printf("결과: %d\n", op(x, y));
}

int main(void) {
    calc(add, 10, 5); // 덧셈
    calc(sub, 10, 5); // 뺄셈
    return 0;
}

👉 출력:

결과: 15
결과: 5

void 포인터란?

  • 자료형이 정해지지 않은 포인터
  • 어떤 타입의 주소든 담을 수 있음
  • 하지만 사용하려면 반드시 형 변환(cast) 필요
#include <stdio.h>

int main(void) {
    int a = 10;
    double d = 3.14;
    void *vp;   // void 포인터

    vp = &a;
    printf("정수값 = %d\n", *(int *)vp);

    vp = &d;
    printf("실수값 = %.2f\n", *(double *)vp);

    return 0;
}

👉 출력:

정수값 = 10
실수값 = 3.14

⚠️ 주의: void * 는 직접 산술 연산(vp+1) 불가능 → 형변환 후 사용해야 함


19-2. main 함수와의 연결성

  • C 프로그램은 main 함수에서 시작
  • main 함수도 함수 포인터로 가리킬 수 있음
  • 프로그램 구조 설계 시 콜백(callback) 개념 구현 가능

예제 (간단한 콜백):

#include <stdio.h>

void hello() { printf("Hello, World!\n"); }

void run(void (*func)()) {
    func();  // 전달된 함수 실행
}

int main(void) {
    run(hello); // 함수 포인터로 전달
    return 0;
}

👉 출력: Hello, World!


핵심 정리 ✅

  • 함수 포인터: 함수 주소 저장 및 호출 가능, 콜백 구현에 활용
  • void 포인터: 모든 타입 주소 저장 가능, 반드시 형 변환 필요
  • 함수 포인터와 void 포인터는 C언어에서 유연한 코드 작성의 핵심

연습 문제 ✍️

  1. 두 정수를 곱하는 mul 함수를 작성하고, 함수 포인터를 통해 호출해 보세요.
  2. 두 개의 함수(덧셈, 나눗셈)를 준비하고, 사용자 선택에 따라 다른 함수를 실행하는 프로그램을 작성하세요.
  3. void 포인터를 이용해 정수와 실수를 하나의 배열처럼 번갈아 출력하는 프로그램을 작성하세요.

 

 

👉 연습문제 정답은? ▼

 

Chapter 19 연습문제 풀이


1) 두 정수를 곱하는 mul 함수를 작성하고, 함수 포인터를 통해 호출하기

#include <stdio.h>

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

int main(void) {
    int (*fp)(int, int);  // 함수 포인터 선언
    fp = mul;             // mul 함수 주소 저장

    int result = fp(3, 4); // 함수 포인터로 호출
    printf("3 * 4 = %d\n", result);
    return 0;
}

👉 출력:

3 * 4 = 12

2) 사용자 선택에 따라 다른 함수 실행 (덧셈 / 나눗셈)

#include <stdio.h>

int add(int a, int b) { return a + b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }

int main(void) {
    int choice, x, y;
    int (*op)(int, int);

    printf("연산 선택 (1: 덧셈, 2: 나눗셈): ");
    scanf("%d", &choice);
    printf("두 정수 입력: ");
    scanf("%d %d", &x, &y);

    if (choice == 1) op = add;
    else op = divide;

    printf("결과 = %d\n", op(x, y));
    return 0;
}

👉 실행 예시

연산 선택 (1: 덧셈, 2: 나눗셈): 1
두 정수 입력: 6 4
결과 = 10
연산 선택 (1: 덧셈, 2: 나눗셈): 2
두 정수 입력: 8 2
결과 = 4

3) void 포인터를 이용해 정수와 실수를 번갈아 출력하기

#include <stdio.h>

int main(void) {
    int a = 10, b = 20;
    double x = 3.14, y = 2.71;
    void *arr[4];  // void 포인터 배열

    arr[0] = &a;
    arr[1] = &x;
    arr[2] = &b;
    arr[3] = &y;

    printf("정수1 = %d\n", *(int *)arr[0]);
    printf("실수1 = %.2f\n", *(double *)arr[1]);
    printf("정수2 = %d\n", *(int *)arr[2]);
    printf("실수2 = %.2f\n", *(double *)arr[3]);

    return 0;
}

👉 출력:

정수1 = 10
실수1 = 3.14
정수2 = 20
실수2 = 2.71

핵심 정리 ✅

  • 함수 포인터를 이용하면 함수를 변수처럼 다룰 수 있다.
  • 조건에 따라 다른 함수를 실행하는 동적 호출 가능하다.
  • void 포인터는 여러 타입을 하나의 배열에 섞어 담을 때 유용하다.

 

반응형