본문 바로가기
C C++/C언어 기초

C언어 - 함수 포인터 및 void 포인터

by Go! Jake 2022. 5. 4.

함수 또한 메모리 공간에 저장이 됩니다. 이 저장된 주소를 가리키는 포인터를 함수 포인터라고 합니다. 이 때 함수 포인터에 대해 알아보도록 하겠습니다.

함수 포인터

배열과 마찬가지로 함수도 함수의 이름이 함수가 저장된 메모리 공간의 주소 값을 의미합니다.

 

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 = &num;
	
	printf("%p\n", ptr);
	
	ptr = Function;
	
	printf("%p", ptr);
	
	return 0;
}

위에서는 두 가지 특이점이 있습니다.

- ptr = &num;을 통해 int형 num의 주소를 받았습니다. int형임에도 불구하고 값을 받았습니다.

- ptr = Function;을 통해 void형 Function의 주소를 받았습니다.

 

즉, 어느 형이든 다 받을 수 있습니다. 다만, 해당 주소의 값을 참조거나 변경할 수는 없습니다.

void형 포인터는 포인터 형을 추후에 결정하는 경우 우선적으로 void를 선언하여 사용할 수 있습니다.

해당 내용은 윤성우 열혈 C프로그래밍을 참조하였습니다.

 

댓글