수색…


소개

함수 포인터는 데이터 유형 대신 함수를 가리키는 포인터입니다. 런타임시 호출 할 함수의 가변성을 허용하는 데 사용할 수 있습니다.

통사론

  • returnType (* name) (매개 변수)

  • typedef returnType (* name) (매개 변수)

  • typedef returnType 이름 (매개 변수);
    이름 * 이름;

  • typedef returnType 이름 (매개 변수);
    typedef 이름 * NamePtr;

함수 포인터 할당

#include <stdio.h>

/* increment: take number, increment it by one, and return it */
int increment(int i)
{
    printf("increment %d by 1\n", i);
    return i + 1;
}

/* decrement: take number, decrement it by one, and return it */
int decrement(int i)
{
    printf("decrement %d by 1\n", i);
    return i - 1;
}

int main(void)
{
    int num = 0;          /* declare number to increment */
    int (*fp)(int);       /* declare a function pointer */

    fp = &increment;      /* set function pointer to increment function */
    num = (*fp)(num);     /* increment num */
    num = (*fp)(num);     /* increment num a second time */

    fp = &decrement;      /* set function pointer to decrement function */
    num = (*fp)(num);     /* decrement num */
    printf("num is now: %d\n", num);
    return 0;
}

함수 포인터 반환

#include <stdio.h>

enum Op
{
  ADD = '+',
  SUB = '-',
};


/* add: add a and b, return result */    
int add(int a, int b)
{
    return a + b;
}

/* sub: subtract b from a, return result */
int sub(int a, int b)
{
    return a - b;
}

/* getmath: return the appropriate math function */
int (*getmath(enum Op op))(int,int)
{
    switch (op)
    {
        case ADD:
            return &add;
        case SUB:
            return &sub;
        default:
            return NULL;
    }
}

int main(void)
{
    int a, b, c;
    int (*fp)(int,int);

    fp = getmath(ADD);

    a = 1, b = 2;
    c = (*fp)(a, b);
    printf("%d + %d = %d\n", a, b, c);
    return 0;
}

모범 사례

typedef 사용

매번 함수 포인터를 선언하는 대신 typedef 를 사용하는 것이 편리 할 수 ​​있습니다.

함수 포인터에 대한 typedef 를 선언하는 구문은 다음과 같습니다.

typedef returnType (*name)(parameters);

예:

함수에 대한 함수 포인터가 다음 compare 같은 것을 기대하는 sort 라는 함수가 있는지 확인하십시오.

compare - 정렬 함수에 제공 될 두 요소의 비교 함수.

"compare"는 두 요소가 같다고 간주되면 0을 반환하고 첫 번째 요소가 후자보다 "큰"경우 양수 값을 반환하고 그렇지 않으면 함수가 음수 값을 반환한다는 것을 의미합니다. 즉 첫 번째 요소가 후자보다 "덜").

typedef 가 없으면 다음과 같은 방식으로 함수 포인터를 함수의 인수로 전달합니다.

void sort(int (*compare)(const void *elem1, const void *elem2)) { 
    /* inside of this block, the function is named "compare" */
}

typedef 사용하여 다음과 같이 작성합니다.

typedef int (*compare_func)(const void *, const void *);

그리고 sort 의 함수 시그니처를 다음과 같이 변경할 수 있습니다.

void sort(compare_func func) { 
    /* In this block the function is named "func" */
}

sort 정의 모두 양식의 모든 함수를 허용합니다.

int compare(const void *arg1, const void *arg2) {
    /* Note that the variable names do not have to be "elem1" and "elem2" */
}

함수 포인터는 타입의 포인터 속성을 포함해야하는 유일한 장소입니다. 예를 들어 typedef struct something_struct *something_type 과 같은 유형을 정의하려고하지 마십시오. 이것은 API 호출자가 직접 액세스하지 않아야하는 멤버가있는 구조 (예 : stdio.h FILE 유형)에 적용됩니다 (이제는 포인터가 아니라는 것을 알 수 있습니다).

문맥 포인터를 얻는다.

함수 포인터는 거의 항상 사용자가 제공 한 void *를 컨텍스트 포인터로 가져야합니다.

/* function minimiser, details unimportant */
double findminimum( double (*fptr)(double x, double y, void *ctx), void *ctx)
{
    ...
    /* repeatedly make calls like this */
    temp = (*fptr)(testx, testy, ctx);
}

/* the function we are minimising, sums two cubics */
double *cubics(double x, double y, void *ctx)
{
    double *coeffsx = ctx;
    double *coeffsy = coeffx + 4;

    return coeffsx[0] * x * x * x + coeffsx[1] * x * x + coeffsx[2] * x + coeffsx[3] +
           coeffsy[0] * y * y * y + coeffsy[1] * y * y + coeffsy[2] * y + coeffsy[3];

} 

void caller()
{
    /* context, the coefficients of the cubics */
    double coeffs[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    double min;

    min = findminimum(cubics, coeffs);       
}

컨텍스트 포인터를 사용한다는 것은 추가 매개 변수가 가리키는 기능에 하드 코딩되거나 사용 전역을 요구할 필요가 없다는 것을 의미합니다.

라이브러리 함수 qsort() 는이 규칙을 따르지 않으며, 흔히 간단한 비교 함수에 대한 문맥없이 빠져 나갈 수 있습니다. 그러나 더 복잡한 것이 있으면 컨텍스트 포인터가 필수적이됩니다.


또한보십시오

함수 포인터

소개

charint 와 마찬가지로 함수는 C의 기본 기능입니다. 따라서 포인터를 선언 할 수 있습니다. 즉, 어떤 함수를 호출 하여 다른 함수를 호출 하여 작업을 수행 할 수 있습니다. 당신이 가지고 예를 들어, graph() 그래프 표시 기능, 당신은에 그래프로 기능하는 전달할 수 graph() .

// A couple of external definitions to make the example clearer
extern unsigned int screenWidth;
extern void plotXY(double x, double y);

// The graph() function.
// Pass in the bounds: the minimum and maximum X and Y that should be plotted.
// Also pass in the actual function to plot.
void graph(double minX, double minY,
           double maxX, double maxY,
           ???? *fn) {            // See below for syntax

    double stepX = (maxX - minX) / screenWidth;
    for (double x=minX; x<maxX; x+=stepX) {

        double y = fn(x);         // Get y for this x by calling passed-in fn()

        if (minY<=y && y<maxY) {
            plotXY(x, y);         // Plot calculated point
        } // if
    } for
} // graph(minX, minY, maxX, maxY, fn)

용법

따라서 위의 코드는 함수가 어떤 함수를 통과했는지 그래프로 나타냅니다. 즉, 함수가 특정 조건을 충족하는 한 그래프로 표시됩니다. 즉, double 인수를 전달하고 double 인수를 double 합니다. sin() , cos() , tan() , exp() 등 많은 함수가 있지만 graph() 자체와 같이 많은 exp() 는 없습니다!

통사론

그렇다면 graph() 로 전달할 수있는 함수와 전달할 수없는 함수를 어떻게 지정 하시겠습니까? 전통적인 방식은 이해하기 쉽지 않은 구문을 사용하는 것입니다.

double (*fn)(double); // fn is a pointer-to-function that takes a double and returns one

위의 문제는 동시에 정의하려고하는 두 가지가 있다는 것입니다 : 함수의 구조와 그것이 포인터라는 사실. 그래서 두 개의 정의를 나누십시오! 그러나 typedef 를 사용하면 더 나은 구문 (읽기 쉽고 이해하기 쉽습니다)을 얻을 수 있습니다.

함수 포인터를 쓰는 것에 대한 니모닉

모든 C 함수는 실제로 코드가있는 프로그램 메모리의 한 지점에 대한 포인터입니다. 함수 포인터의 주요 용도는 다른 함수에 "콜백"을 제공하거나 클래스와 객체를 시뮬레이트하는 것입니다.

이 페이지에서 더 자세히 정의 된 함수 구문은 다음과 같습니다.

returnType (* name) (매개 변수)

함수 포인터 정의를 작성하기위한 니모닉은 다음 프로 시저입니다.

  1. 일반 함수 선언을 작성하여 시작하십시오. returnType name(parameters)
  2. 포인터 구문을 사용하여 함수 이름을 래핑하십시오. returnType (*name)(parameters)

기초

그냥 int , char , float , array / string , struct 등등에 대한 포인터를 가질 수있는 것처럼 함수에 대한 포인터를 가질 수 있습니다.

포인터를 선언하면 함수반환 값, 함수이름인수 / 매개 변수유형이 사용 됩니다.

다음 함수를 선언하고 초기화했다고 가정 해보십시오.

int addInt(int n, int m){
    return n+m;
}

이 함수에 대한 포인터를 선언하고 초기화 할 수 있습니다.

int (*functionPtrAdd)(int, int) = addInt; // or &addInt - the & is optional

void 함수를 사용하면 다음과 같이 보일 수 있습니다.

void Print(void){
    printf("look ma' - no hands, only pointers!\n");
}

포인터를 선언하면 다음과 같습니다.

void (*functionPtrPrint)(void) = Print;

함수 자체에 액세스 하려면 포인터의 역 참조가 필요합니다.

sum = (*functionPtrAdd)(2, 3); //will assign 5 to sum
(*functionPtrPrint)(); //will print the text in Print function

이 문서의보다 진보 된 예제에서 볼 수 있듯이 함수에 대한 포인터를 선언하면 함수가 몇 개 이상의 매개 변수를 넘어 서면 지저분해질 수 있습니다. 동일한 "구조체"(반환 값의 동일한 유형 및 동일한 유형의 매개 변수)을 가진 함수에 대한 몇 가지 포인터가있는 경우 typedef 명령을 사용하여 입력 내용을 저장하고 코드를 더 명확하게 작성하는 것이 가장 좋습니다.

typedef int (*ptrInt)(int, int);

int Add(int i, int j){
    return i+j;
}

int Multiply(int i, int j){
    return i*j;
}

int main()
{
    ptrInt ptr1 = Add;
    ptrInt ptr2 = Multiply;

    printf("%d\n", (*ptr1)(2,3)); //will print 5
    printf("%d\n", (*ptr2)(2,3)); //will print 6
    return 0;
}

함수 포인터배열을 만들 수도 있습니다. 모든 포인터가 같은 "구조"의 경우 :

int (*array[2]) (int x, int y); // can hold 2 function pointers
array[0] = Add;
array[1] = Multiply;

여기여기에서 더 많은 것을 배울 수 있습니다.

다른 유형의 함수 포인터 배열을 정의 할 수도 있습니다.하지만 특정 함수에 액세스하려고 할 때 항상 캐스팅이 필요합니다. 자세한 내용은 여기를 참조 하십시오 .



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow