함수도 하나의 DataType입니다. 명령어를 저장하는 DataType입니다. 따라서 함수도 메모리공간에 할당됩니다. 그 말은 즉, 주소값을 가집니다. 그래서 함수도 함수 포인터로 가리킬 수가 있습니다.

함수의 주소값을 값으로 갖는 변수를 함수 포인터 변수라고 합니다. 선언방식은 위의 그림과 같습니다.
포인터에 대해 많이 알고 계시다고 가정하고, 바로 예시 하나 보겠습니다.
예시
#include <stdio.h>
float add(int a, int b) {
return a + b;
}
float sub(int a, int b) {
return a - b;
}
float mul(int a, int b) {
return a * b;
}
float div2(int a, int b) {
return a / (float)b;
}
int main() {
int a = 20;
int b = 30;
float (*pfunc)(int, int);
pfunc = add;
printf("add함수의 주소값 %p\n", add);
float fret = pfunc(a, b);
printf("%d + %d = %f\n", a, b, fret);
pfunc = ⊂
fret = pfunc(a, b);
printf("%d - %d = %f\n", a, b, fret);
pfunc = &mul;
fret = pfunc(a, b);
printf("%d * %d = %f\n", a, b, fret);
pfunc = &div2;
fret = pfunc(a, b);
printf("%d / %d = %f\n", a, b, fret);
return 0;
}
결과
add함수의 주소값 00007FF681EE12C1
20 + 30 = 50.000000
20 - 30 = -10.000000
20 * 30 = 600.000000
20 / 30 = 0.666667
참고 함수명 자체가 함수의 주소값이기 때문에 주소연산자(&)를 붙이든 안붙이든 관계가 없습니다. 그리고 함수 포인터 변수를 선언할 때 주소값을 가져올 함수의 반환형과 매개변수의 개수와 종류가 모두 함수 포인터 변수와 같아야합니다.
함수 포인터 변수도 변수입니다. 따라서 다른 함수의 인자값으로 보낼 수가 있습니다.
예시
#include <stdio.h>
float add(int a, int b) {
return a + b;
}
float sub(int a, int b) {
return a - b;
}
float mul(int a, int b) {
return a * b;
}
float div2(int a, int b) {
return a / (float)b;
}
float calculator(float(*pfunc)(int, int), int a, int b) {
return pfunc(a, b);
}
int main() {
int a = 20;
int b = 30;
char oper = 0;
float fret = 0;
printf("연산 방법을 입력하세요(+,-,*,/): ");
scanf_s("%c", &oper);
switch (oper) {
case '+':
fret = calculator(add, a, b);
printf("%d + %d = %f\n", a, b, fret);
break;
case '-':
fret = calculator(sub, a, b);
printf("%d - %d = %f\n", a, b, fret);
break;
case '*':
fret = calculator(mul, a, b);
printf("%d * %d = %f\n", a, b, fret);
break;
case '/':
fret = calculator(div2, a, b);
printf("%d / %d = %f\n", a, b, fret);
break;
default:
printf("연산 기호를 잘못 입력하셨습니다.\n");
break;
}
return 0;
}
결과
연산 방법을 입력하세요(+,-,*,/): +
20 + 30 = 50.000000
연산 방법을 입력하세요(+,-,*,/): -
20 - 30 = -10.000000
연산 방법을 입력하세요(+,-,*,/): *
20 * 30 = 600.000000
연산 방법을 입력하세요(+,-,*,/): /
20 / 30 = 0.666667
함수 포인터 변수도 함수형 포인터형인 DataType을 가집니다. 따라서 배열의 DataType으로 선언이 가능합니다.
위 그림 처럼 함수형 포인터형 배열을 선언하고, 각 요소의 값으로 함수명(함수의 주소값)을 주면 됩니다.
예시
#include <stdio.h>
float add(int a, int b) {
return a + b;
}
float sub(int a, int b) {
return a - b;
}
float mul(int a, int b) {
return a * b;
}
float div(int a, int b) {
return a / (float)b;
}
int main() {
int a = 20;
int b = 30;
char oper = 0;
float fret = 0;
int operNum = 0;
char operArray[] = { '+', '-', '*', '/' };
float(*operfuncArray[4])(int, int); //함수 포인터 배열 선언
operfuncArray[0] = add;
operfuncArray[1] = sub;
operfuncArray[2] = mul;
operfuncArray[3] = div;
printf("연산 방법을 입력하세요(+, -, *, /): ");
scanf_s("%c", &oper);
operNum = -1;
for (int i = 0; i < 4; i++) {
if (operArray[i] == oper) {
operNum = i;
break;
}
}
if (operNum != -1) {
printf("%d %c %d = %f\n", a, operArray[operNum], b, operfuncArray[operNum](a, b));
}
else {
printf("연산기호를 잘못 입력하셨습니다.\n");
}
//함수를 배열에 넣고 일괄적으로 처리
printf("\n\n일괄 연산 처리\n");
for (int i = 0; i < 4; i++) {
printf("%d %c %d = %f\n", a, operArray[i], b, operfuncArray[i](a, b));
}
return 0;
}
결과
연산 방법을 입력하세요(+, -, *, /): +
20 + 30 = 50.000000
일괄 연산 처리
20 + 30 = 50.000000
20 - 30 = -10.000000
20 * 30 = 600.000000
20 / 30 = 0.666667
함수와 포인터가 섞여서 어려울 것같지만 주소값과 포인터의 이해만 있다면, 어려운게 없는 것 같습니다.