함수 또한 메모리 공간에 저장이 됩니다. 이 저장된 주소를 가리키는 포인터를 함수 포인터라고 합니다. 이 때 함수 포인터에 대해 알아보도록 하겠습니다.
함수 포인터
배열과 마찬가지로 함수도 함수의 이름이 함수가 저장된 메모리 공간의 주소 값을 의미합니다.
int Function(int num){...}의 함수를 선언한 경우
- 맨 앞 bold체 int는 함수의 반환형이 됩니다.
- 그 이후 괄호 안에 인자로 int num은 매개 변수가 됩니다. 실제 함수에 입력되는 값을 받아주는 것입니다.
- 함수의 형(type)을 정의할 때는, 반환형이 int이고 하나의 int형 변수가 선언된 포인터 형이라고 할 수 있습니다.
함수 포인터 변수의 선언
함수 포인터는 어떻게 선언할까요? 아래와 같이 선언할 수 있습니다.
int (*fptr) (int)
예시 1) 매개변수 선언이 int인 함수 포인터입니다. 함수를 가리키게하면 아래와 같습니다.
#include <stdio.h>
void ShowInfo(int a)
{
printf("%d\n", a);
}
int main(){
int b = 1;
ShowInfo(b);
void (*fptr)(int);
fptr=ShowInfo;
fptr(b);
return 0;
}
출력:
1
1
놀랍게도, fptr(b);로도 ShowInfo가 동일하게 동작하였습니다.
- void ShowInfo(int a)를 선언합니다.
- main 함수 내에서 void (*fptr)(int);를 정의합니다. void 반환형은 ShowInfo와 동일하게 void로 맞춘 것입니다.
- fptr = ShowInfo;로 정의합니다. fptr이 ShowInfo 함수를 가리키는 것입니다. 앞 서 말한 것과 같이 함수의 이름은 주소 값과 같다고 말씀드렸습니다.
- 이제, fptr을 ShowInfo함수처럼 사용하면 됩니다. fptr(b);로도 ShowInfo(b);와 동일한 효과가 났습니다.
예시 2) 함수 포인터 변수가 매개 변수로 오는 경우
#include <stdio.h>
int sorting(int num1, int num2, int (*cmp)(int n1, int n2))
{
return cmp(num1, num2);
}
int big(int num1, int num2)
{
if (num1>num2)
{
return num1;
}
else
{
return num2;
}
}
int small(int num1, int num2)
{
if (num1<num2)
{
return num1;
}
else
{
return num2;
}
}
int main(){
int number1 = 1;
int number2 = 2;
int result;
result = sorting(number1, number2, small);
printf("smaller value: %d\n", result);
result = sorting(number1, number2, big);
printf("bigger value: %d\n", result);
return 0;
}
출력:
smaller value: 1
bigger value: 2
위 목적은 두 값이 sorting의 인자로 들어 왔을 때, 세 번째 인자에 따라 두 값 중 작은 값이 표출되거나 큰 값이 표출되도록 만든 함수입니다. small인 경우 작은 값, big인 경우 큰 값이 result에 저장된 후 표출됩니다.
1)
Sorting 함수: 세 번째 인자로 함수를 전달받습니다. 이 때 함수의 이름을 전달받아야 합니다.
int sorting(int num1, int num2, int (*cmp)(int n1, int n2))
{
return cmp(num1, num2);
}
2)
main 함수에서 각각
- result = sorting(number1, number2, small);
- result = sorting(number1, number2, big);
으로 result에 저장된 값이 달라지는 것을 알 수 있습니다. 세 번째 인자로 함수 이름, 즉 주소 값을 넣으면 사용할 수 있습니다.
형(type)이 존재하지 않는 void 포인터
아래와 같은 포인터 변수를 void형 포인터 변수라고 합니다.void* ptr;
void형 포인터 변수는 무엇이든 담을 수 있습니다.
#include <stdio.h>
void Function(void)
{
printf("Hello World");
}
int main()
{
int num = 20;
void* ptr;
ptr = #
printf("%p\n", ptr);
ptr = Function;
printf("%p", ptr);
return 0;
}
위에서는 두 가지 특이점이 있습니다.
- ptr = #을 통해 int형 num의 주소를 받았습니다. int형임에도 불구하고 값을 받았습니다.
- ptr = Function;을 통해 void형 Function의 주소를 받았습니다.
즉, 어느 형이든 다 받을 수 있습니다. 다만, 해당 주소의 값을 참조거나 변경할 수는 없습니다.
void형 포인터는 포인터 형을 추후에 결정하는 경우 우선적으로 void를 선언하여 사용할 수 있습니다.
해당 내용은 윤성우 열혈 C프로그래밍을 참조하였습니다.
'C C++ > C언어 기초' 카테고리의 다른 글
C언어 - 구조체 배열과 포인터 (0) | 2022.05.05 |
---|---|
C언어 - 구조체란? (구조체 정의, 구조체 변수의 초기화) (0) | 2022.05.05 |
C언어 - 포인터와 함수 관계의 모든 것 (0) | 2022.05.03 |
C언어 - 포인터 배열의 이해 : 포인터 변수로 이뤄진 배열 (0) | 2022.05.02 |
C언어 - 포인터와 배열 이해의 모든 것 (배열 이름, 포인터로 배열 가리키기, 상수 형태 문자열의 포인터) (0) | 2022.05.02 |
댓글