함수 자체를 어디다 저장해 둔 뒤 매개변수로 전달 할 수는 없을까?
함수를 호출하면 어떤 일이 일어나지?
어셈블리어를 까보면...컴퓨터가 하는일은 함수를 호출했을 때 그 함수가 시작되는 주소로 점프
이 주소 : 함수가 시작되는 주소는 컴파일 도중에 정해지는 주소. (실행중에 바뀌는 주소는 아니다)
하지만 함수가 반환해서 돌아가는 주소는 실행도중에 변경된다.
// 함수 호출시 스택메모리 구조
|------호출자 스택프레임------|
|----00E211AB(돌아갈주소)----|
|----호출된함수 스택프레임-----|
|---------------------------|
함수를 실행시키려면? 함수가 시작하는 메모리 주소를 알면된다!
즉 함수포인터는 함수가 시작하는 코드 주소를 저장하는 포인터 변수
매개변수로 전달되는 함수는 다음과 같은 내용도 포함해야한다.
double add(double x, double y){
return x + y;
}
/*
함수 포인터의 선언
1. func는 변수명 (포인터 변수)
2. 변수에 저장되는 주소는 반환타입 double, 매개변수 (double, double)의 함수의 시작 주소
3. 시작주소를 가져올 함수는 바로 add (괄호 생략해서 대입)
*/
double (*func)(double, double) = add;
// 결과값은 op1 + op2 반환 --> func에 대입한 이후 함수처럼 똑같이 사용가능하다.
result = func(op1, op2);
함수포인터 매개변수로 사용
double calculate (double x, double y, double (*func)(double, double))
{
return func(x, y);
}
result = calculate(op1, op2, add);
함수 포인터의 배열도 가능
int add(int x, int y){
return x + y;
}
int sub(int x, int y){
return x - y;
}
int mul(int x, int y){
return x * y;
}
int div(int x, int y){
return x / y;
}
int (*ops[])(int, int) = {add, sub, mul, div};
어떤 조건에 따라 실행되는 함수를 다르게 하고 싶을 때 (반환형, 매개변수 타입이 동일)
C#
에서 delegate
도 사실 함수 포인터
JavaScript
에서도 비슷한 개념으로 사용
var bar = function() {alert("Hello"); }
var foo = bar;
bar = function() {alert("Good Bye"); }
foo(); // Hello 출력 --> foo에는 이전 함수의 시작주소가 저장되어있다.
퀵정렬 함수
/*
<stdlib.h>안에 있는 표준 라이브러리 함수
정렬할 배열의 시작주소, 요소수, 각요소의 크기, 정렬기준
*/
void qsort(void *ptr, size_t count, size_t size, int (*comp)(const void*, const void*));
모든 포인터를 대입가능한 범용적 포인터
데이터 크기를 알아야하는 연산은 불가 (역참조, 포인터 산술연산 등)