C 언어에서 함수 포인터 활용과 계산기 구현 방법 3가지

함수 포인터 변수란?

함수 포인터는 특정 함수의 시작 주소를 저장할 수 있는 포인터입니다. 이를 통해 함수를 직접 호출하는 대신, 포인터를 통해 간접적으로 함수를 실행할 수 있습니다. C 언어에서 함수 이름 자체가 그 함수의 주소를 의미하므로, 다음과 같이 출력하여 확인할 수 있습니다.

#include <stdio.h>

void PrintMessage() {
    printf("Hello from function!\n");
}

int main() {
    printf("함수 주소: %p\n", (void*)PrintMessage);
    printf("함수 주소(& 사용): %p\n", (void*)&PrintMessage);
    return 0;
}

위 코드에서 두 주소 값은 동일하게 출력됩니다. 이는 함수명이 곧 주소임을 보여줍니다.

함수 포인터의 타입 선언

함수 포인터의 형식은 반환형, 매개변수의 수와 타입을 정확히 지정해야 합니다. 예를 들어, 두 개의 정수를 받아 정수를 반환하는 함수의 포인터는 다음과 같이 선언합니다.

int (*funcPtr)(int, int);
  • funcPtr: 포인터 변수 이름
  • int: 함수의 반환 타입
  • (int, int): 함수가 받는 인자의 타입

실제로 이를 이용해 덧셈 함수를 호출하는 예제는 아래와 같습니다.

#include <stdio.h>

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

int main() {
    int (*operation)(int, int) = Add;
    int x = 5, y = 3;

    printf("결과: %d\n", operation(x, y));  // 또는 (*operation)(x, y)
    return 0;
}

함수 포인터로 호출할 때 괄호 안에 *를 넣는 것은 문법적으로 가능하지만 생략 가능합니다. 컴파일러가 자동으로 해석합니다.

함수 포인터 배열

여러 함수를 하나의 배열에 저장하면, 조건에 따라 적절한 함수를 선택하여 호출할 수 있습니다. 이를 함수 포인터 배열이라 부릅니다. 선언 방식은 다음과 같습니다.

int (*ptrArray[5])(int, int);

배열의 각 요소는 같은 시그니처(반환형과 매개변수)를 가진 함수를 가리켜야 합니다. 인덱스 0은 종종 사용하지 않거나 NULL로 설정합니다.

계산기 프로그램의 세 가지 구현 방식

방법 1: 전통적인 switch-case 기반 구현

각 연산마다 별도의 함수를 만들고, 사용자 입력에 따라 switch 문으로 분기합니다. 단점은 중복된 입력 처리 코드가 반복된다는 점입니다.

#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) { return b != 0 ? a / b : 0; }

void ShowMenu() {
    printf("\n=== 계산기 ===\n");
    printf("1. 덧셈  2. 뺄셈\n");
    printf("3. 곱셈  4. 나눗셈\n");
    printf("0. 종료\n");
    printf("선택: ");
}

int main() {
    int choice, x, y;
    do {
        ShowMenu();
        scanf("%d", &choice);

        if (choice == 0) {
            printf("프로그램 종료.\n");
            break;
        }

        printf("두 숫자 입력: ");
        scanf("%d %d", &x, &y);

        switch (choice) {
            case 1:
                printf("결과: %d\n", Add(x, y));
                break;
            case 2:
                printf("결과: %d\n", Subtract(x, y));
                break;
            case 3:
                printf("결과: %d\n", Multiply(x, y));
                break;
            case 4:
                if (y == 0) {
                    printf("오류: 0으로 나눌 수 없습니다.\n");
                } else {
                    printf("결과: %d\n", Divide(x, y));
                }
                break;
            default:
                printf("잘못된 선택입니다.\n");
        }
    } while (1);

    return 0;
}

방법 2: 함수 포인터 배열 사용

중복된 scanf 및 출력 코드를 제거하고, 함수 포인터 배열을 이용해 연산을 매핑합니다. 유지보수성과 확장성이 향상됩니다.

#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) { return b != 0 ? a / b : 0; }

void ShowMenu() {
    printf("\n=== 계산기 (포인터 배열) ===\n");
    printf("1. 덧셈  2. 뺄셈  3. 곱셈  4. 나눗셈\n");
    printf("0. 종료\n");
    printf("선택: ");
}

int main() {
    // 함수 포인터 배열 초기화 (인덱스 0은 NULL)
    int (*ops[])(int, int) = {NULL, Add, Subtract, Multiply, Divide};
    int choice, x, y;

    do {
        ShowMenu();
        scanf("%d", &choice);

        if (choice == 0) {
            printf("종료합니다.\n");
            break;
        }

        if (choice >= 1 && choice <= 4) {
            printf("두 수 입력: ");
            scanf("%d %d", &x, &y);
            printf("결과: %d\n", ops[choice](x, y));
        } else {
            printf("잘못된 입력입니다.\n");
        }
    } while (1);

    return 0;
}

방법 3: 함수 포인터를 인자로 전달

공통 로직을 별도의 함수로 추출하고, 연산 함수를 인자로 전달합니다. 코드 재사용성이 극대화됩니다.

#include <stdio.h>

int Add(int a, int b) { return a + b; }
int Subtract(int a, int b) { return a - b; }

void ExecuteOperation(int (*operation)(int, int)) {
    int x, y;
    printf("두 수 입력: ");
    scanf("%d %d", &x, &y);
    printf("결과: %d\n", operation(x, y));
}

void ShowMenu() {
    printf("\n=== 계산기 (함수 포인터 전달) ===\n");
    printf("1. 덧셈  2. 뺄셈  0. 종료\n");
    printf("선택: ");
}

int main() {
    int choice;
    do {
        ShowMenu();
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                ExecuteOperation(Add);
                break;
            case 2:
                ExecuteOperation(Subtract);
                break;
            case 0:
                printf("종료합니다.\n");
                break;
            default:
                printf("잘못된 선택.\n");
        }
    } while (choice != 0);

    return 0;
}

태그: C 함수 포인터 포인터 배열 계산기 구현 콜백 함수

6월 29일 21:07에 게시됨