프로그래밍 언어 공부/C

함수 포인터(Function Pointer)

CalebHong 2022. 1. 15. 17:07

함수 포인터란?

- 함수의 주소를 저장하는 변수

 

필요성

  1. 프로그램 코드 간결화
  2. 배열로 처리함으로써 중복 코드 제거 가능
  3. 상황에 따른 함수 호출
  4. 함수를 데이터 형태로 처리 → 함수의 보관과 전달이 용이

 

형식

- 리턴 타입 (*함수 포인터명)(매개변수 리스트);

 

1. 리턴과 매개변수가 없는 함수에 대한 함수 포인터

#include <stdio.h>

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

void good()
{
	printf("Good morning!\n");
}

int main()
{
	void (*fp)(); // 함수 포인터 선언(리턴타입void, 매개변수 없음)
    
    fp = hello; // hello 함수 시작 주소를 대입
    fp(); // 함수 포인터로 호출
    
    fp = good; // good 함수 시작 주소를 대입
    fp(); // 함수 포인터로 호출
    
    return 0;
}

 

2. 리턴과 매개변수가 있는 함수에 대한 함수 포인터

#include <stdio.h>

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

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

int main()
{
	int (*fp)(int, int); // int를 리턴하고, int형 2개를 매개변수로 하는 함수 포인터 선언
    
    fp = add; // 함수 포인터에 add함수 대입(함수 포인터의 타입과 매개변수가 동일해야 대입 가능)
    printf("%d\n", fp(10, 20)); // 함수 포인터 호출
    
    fp = sub; // 함수 포인터에 sub함수 대입
    printf("%d\n", fp(10, 20)); // 함수 포인터 호출
    
    return 0;
}

 

3. 함수 포인터 배열

배열 사용 전

#include <stdio.h>

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

int main()
{
    int funcNumber;
    int num1, num2;
    int (*fp)(int, int) = NULL; // 선언 단계에서 따로 초기화 하지 않으면 가능하면 NULL로 초기화
    printf("함수 번호와 계산할 값을 입력하세요: ");
    scanf("%d %d %d", &funcNumber, &num1, &num2);
    
    switch(funcNumber)
    {
    	case 1:
        	fp = add;
        	break;
        case 2:
        	fp = sub;
            break;
    }
    printf(%d\n", fp(num1, num2));
    
    return 0;
}

배열 사용 후

#include <stdio.h>

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

int main()
{
    int funcNumber;
    int num1, num2;
    int (*fp[2])(int, int);
    
    fp[0] = add;
    fp[1] = sub;
    
    // 또는  int (*fp[2])(int, int) = {add, sub}; 로 선언과 초기화 가능
    
    printf("함수 번호와 계산할 값을 입력하세요: ");
    scanf("%d %d %d", &funcNumber, &num1, &num2);
    
    printf(%d\n", fp[funcNumber](num1, num2));
    
    return 0;
}

 

4. 구조체 멤버

#include <stdio.h>

struct Calc { int (*fp)(int, int); }; // 구조체가 함수를 포함하는 형태로 구현 가능

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

int main()
{
    struct Calc c;
    
    c.fp = add;
    
    printf("%d\n", c.fp(10, 20));
    
    return 0;
}

 

5. 함수의 매개변수

#include <stdio.h>

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

void calc(int (*fp)(int, int)) // 함수의 매개변수로 포인터 변수가 사용됨
{
    printf("%d\n", fp(10, 20));
}

int main()
{
    calc(add);
    
    return 0;
}

 

함수 포인터 활용

1. qsort()

항 목 내 용
함수원형 void qsort(void* base, size_t num, size_t size, int(*compar)(const void*, const void));
헤더 stdlib.h
기능 테이블의 자료를 퀵 정렬로 내림이나 오름차순으로 정렬
매개변수 void* base : 테이블의 포인터 주소
size_t num : 테이블에 들어 있는 실제 데이터 갯수
size_t size : 한 개 요소의 크기
int(*compar)(const void*, const void) : 두 요소를 비교하기 위한 함수 포인터
반환값 void
구현 비교함수는 직접 구현해야 함
(배열의 자료형과 비교방식이 다르기 때문)

예제

#include <stdio.h>
#include <stdlib.h>

int compare(const void* cmp1, const void* cmp2)
{
	// 같으면 0을 반환, 다르다면 앞에가 크면 0보다 큰 값, 뒤에가 크면 0보다 작은 값을 반환
    return strcmp((char*) cmp1, (char*) cmp2);
}

#define SIZE_TABLE 10
#define SIZE_ITEM 100

int main(void)
{
	char table[SIZE_TABLE][SIZE_ITEM] = 
    {
    	"good", "hello", "hi", "morning", "computer", "GCC", "Programming"
    };
    int ndx;
    
    for (ndx=0; ndx < SIZE_TABLE; ndx++) 
    	printf("%s\n", table[ndx]);
    
    printf("n정렬 후n");
    
    qsort(table, SIZE_TABLE, SIZE_ITEM, compare);
    
    for (ndx=0; ndx < SIZE_TABLE; ndx++) 
    	printf("%s\n", table[ndx]);
        
    return 0;
}

예제 2

#include <stdio.h>
#include <stdlib.h>

int values[] = { 40, 10, 100, 90, 20, 25 };

int compare (const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}

int main()
{
    int n;
    qsort(value, 6, sizeof(int), compare);
    for (n=0; n<6; n++)
    	printf("%d ", values[n]);
    return 0;
}