함수 포인터

함수의 주소

다른 데이터 항목과 마찬가지로 정의된 함수는 메모리(텍스트 세그먼트)에 로드되고 프로그램이 실행될 때 주소를 갖습니다. 이 시점에서 함수의 이름은 실제로 함수의 시작 주소를 가리키는 상수 포인터입니다. 함수 이름과 같은 함수의 시작 주소에 대한 const 포인터. 함수 포인터그것은 말한다. 함수 포인터는 함수를 다른 함수의 인수로 전달할 때 유용합니다.

test();		함수
test		함수의 주소 (즉, 함수를 지시하는 '함수 포인터')

함수 포인터 선언

포인터를 선언하려면 포인터가 가리키는 데이터 유형을 정확히 지정해야 합니다. 즉, 함수 포인터 선언은 함수의 반환 유형, 매개변수 수 및 데이터 유형을 전달해야 합니다.

double pam(int n);		함수 원형
double (*pa)(int);		함수 포인터
pa = pam;

함수 포인터 사용

함수 포인터를 선언하면 함수처럼 사용할 수 있습니다. 그러나 이것은 까다로운 일이 발생하는 곳입니다.

double x = pam(4);		pam()은 함수, pam은 함수 포인터
double x = pa(4);		pa()는 함수, pa는 함수 포인터. 그렇다면 *pa는??

pa는 함수 포인터이므로 함수는 *pa여야 합니다. 그러나 함수 이름은 함수 포인터로 간주되므로 함수 포인터 pa 자체를 함수 이름으로 사용할 수 있습니다. 즉, pa와 *pa는 모두 함수 이름(함수 포인터)과 동일한 의미를 갖습니다. 아래 코드는 동일한 명령 주소(기능)를 가지며 동일한 작업을 수행합니다.

double x = pam(4);
double x = pa(4);
double x = (*pa)(4)

함수 포인터 배열

함수 포인터는 다른 포인터처럼 배열을 만들 수 있습니다. 선언문은 다음과 같습니다.

double (*pb(3))(int);		//연산자 우선순위는 ()가 *보다 높다.

*pb(3) 포인터의 배열
(*pb)(3) 원소 3개인 배열을 지시하는 포인터

배열, 포인터 및 함수 혼합

일반 데이터 유형의 배열, 포인터를 반환하는 함수, 해당 함수를 가리키는 함수 포인터, 함수 포인터 배열, 함수 포인터 배열을 가리키는 포인터. 다음 코드는 모두 동시에 사용할 것이기 때문에 조금 더 복잡해집니다. 이들의 관계를 잘 살펴보자.

//포인터를 그대로 반환하는 함수
const double* f1(const double*, int);
const double* f2(const double*, int);
const double* f3(const double*, int);

int main()
{
	//배열
	double a(3) = { 11.1, 22.2,33.3 };

	//함수 포인터
	const double* (*pa)(const double*, int) = f1;

	//함수 포인터의 배열
	const double* (*pb(3))(const double*, int) = { f1,f2,f3 };

	//함수 포인터 배열을 가르키는 포인터
	const double* (*(*pc)(3))(const double*, int) = &pb;

	return 0;
}

pc는 함수 포인터의 배열을 가리키는 포인터입니다.

*pc는 함수 포인터의 배열입니다. B.pb. *pc == pb

따라서 (*pc)(0)은 함수 포인터입니다. (*pc)(0) == pb(0)

위 함수 포인터는 함수 이름으로 사용하기 때문에 생략하고 함수 이름으로 사용한다. 따라서 ((*pc)(0))은 위와 동일한 함수 포인터입니다. (개)(0) == pb(0) == ((*개)(0))

(*pc)(0)은 함수 f1을 가리키는 함수 포인터입니다. (pc)(0) == ((*pc)(0)) == pb(0) == f1

(*pc)(0)(a, 3)은 배열 a의 주소를 반환합니다. (*pc)(0)(a, 3) == f1(a,3)

((*pc)(0)(a, 3))(2)는 배열 a의 세 번째 요소인 33.3입니다.

보시다시피 함수 포인터는 복잡하고 불편하기 때문에 auto 또는 typedef 자동 데이터 유형을 자주 사용합니다.