[c] 함수 포인터 배열을 어떻게 사용합니까?

C에서 함수 포인터 배열을 어떻게 사용해야합니까?

어떻게 초기화 할 수 있습니까?



답변

여기구문이 상세한 ( 함수 포인터의 배열) 좋은 예가 있습니다 .

int sum(int a, int b);
int subtract(int a, int b);
int mul(int a, int b);
int div(int a, int b);

int (*p[4]) (int x, int y);

int main(void)
{
  int result;
  int i, j, op;

  p[0] = sum; /* address of sum() */
  p[1] = subtract; /* address of subtract() */
  p[2] = mul; /* address of mul() */
  p[3] = div; /* address of div() */
[...]

해당 함수 포인터 중 하나를 호출하려면

result = (*p[op]) (i, j); // op being the index of one of the four functions


답변

위의 답변이 도움이 될 수 있지만 함수 포인터 배열을 사용하는 방법을 알고 싶을 수도 있습니다.

void fun1()
{

}

void fun2()
{

}

void fun3()
{

}

void (*func_ptr[3])() = {fun1, fun2, fun3};

main()
{
    int option;


    printf("\nEnter function number you want");
    printf("\nYou should not enter other than 0 , 1, 2"); /* because we have only 3 functions */
    scanf("%d",&option);

    if((option>=0)&&(option<=2))
    {
        (*func_ptr[option])();
    }

    return 0;
}

단일 함수 포인터 배열에 동일한 반환 유형과 동일한 인수 유형 및 인수가없는 함수의 주소 만 할당 할 수 있습니다.

위의 모든 함수에 동일한 유형의 동일한 수의 인수가있는 경우 다음과 같은 인수를 전달할 수도 있습니다.

  (*func_ptr[option])(argu1);

참고 : 배열에서 함수 포인터의 번호는 일반적인 배열과 같은 0부터 시작합니다. 따라서 위의 예에서 fun1option = 0 인 fun2경우 호출 할 수 있고 option = 1 fun3인 경우 호출 할 수 있으며 option = 2 인 경우 호출 할 수 있습니다.


답변

사용 방법은 다음과 같습니다.

New_Fun.h

#ifndef NEW_FUN_H_
#define NEW_FUN_H_

#include <stdio.h>

typedef int speed;
speed fun(int x);

enum fp {
    f1, f2, f3, f4, f5
};

void F1();
void F2();
void F3();
void F4();
void F5();
#endif

New_Fun.c

#include "New_Fun.h"

speed fun(int x)
{
    int Vel;
    Vel = x;
    return Vel;
}

void F1()
{
    printf("From F1\n");
}

void F2()
{
    printf("From F2\n");
}

void F3()
{
    printf("From F3\n");
}

void F4()
{
    printf("From F4\n");
}

void F5()
{
    printf("From F5\n");
}

Main.c

#include <stdio.h>
#include "New_Fun.h"

int main()
{
    int (*F_P)(int y);
    void (*F_A[5])() = { F1, F2, F3, F4, F5 };    // if it is int the pointer incompatible is bound to happen
    int xyz, i;

    printf("Hello Function Pointer!\n");
    F_P = fun;
    xyz = F_P(5);
    printf("The Value is %d\n", xyz);
    //(*F_A[5]) = { F1, F2, F3, F4, F5 };
    for (i = 0; i < 5; i++)
    {
        F_A[i]();
    }
    printf("\n\n");
    F_A[f1]();
    F_A[f2]();
    F_A[f3]();
    F_A[f4]();
    return 0;
}

이것이 이해하는 데 도움이되기를 바랍니다. Function Pointer.


답변

이 “답변”은 VonC의 답변에 대한 부록입니다. 구문은 typedef를 통해 단순화 될 수 있으며 집계 초기화를 사용할 수 있습니다.

typedef int FUNC(int, int);

FUNC sum, subtract, mul, div;
FUNC *p[4] = { sum, subtract, mul, div };

int main(void)
{
    int result;
    int i = 2, j = 3, op = 2;  // 2: mul

    result = p[op](i, j);   // = 6
}

// maybe even in another file
int sum(int a, int b) { return a+b; }
int subtract(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int div(int a, int b) { return a/b; }


답변

아, 많은 예가 있습니다. glib 또는 gtk 내의 내용을 살펴보십시오. 작업에서 함수 포인터의 작업을 끝까지 볼 수 있습니다.

여기 예를 들어 gtk_button 항목의 초기화.


static void
gtk_button_class_init (GtkButtonClass *klass)
{
  GObjectClass *gobject_class;
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

  gobject_class = G_OBJECT_CLASS (klass);
  object_class = (GtkObjectClass*) klass;
  widget_class = (GtkWidgetClass*) klass;
  container_class = (GtkContainerClass*) klass;

  gobject_class->constructor = gtk_button_constructor;
  gobject_class->set_property = gtk_button_set_property;
  gobject_class->get_property = gtk_button_get_property;

그리고 gtkobject.h에는 다음과 같은 선언이 있습니다 :


struct _GtkObjectClass
{
  GInitiallyUnownedClass parent_class;

  /* Non overridable class methods to set and get per class arguments */
  void (*set_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);
  void (*get_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);

  /* Default signal handler for the ::destroy signal, which is
   *  invoked to request that references to the widget be dropped.
   *  If an object class overrides destroy() in order to perform class
   *  specific destruction then it must still invoke its superclass'
   *  implementation of the method after it is finished with its
   *  own cleanup. (See gtk_widget_real_destroy() for an example of
   *  how to do this).
   */
  void (*destroy)  (GtkObject *object);
};

(* set_arg) 항목은 함수에 대한 포인터이며, 예를 들어 일부 파생 클래스에서 다른 구현에 할당 될 수 있습니다.

종종 당신은 이와 같은 것을 본다

struct function_table {
   char *name;
   void (*some_fun)(int arg1, double arg2);
};

void function1(int  arg1, double arg2)....


struct function_table my_table [] = {
    {"function1", function1},
...

따라서 이름으로 테이블에 접근하여 “연관된”기능을 호출 할 수 있습니다.

또는 함수를 넣고 “이름으로”호출하는 해시 테이블을 사용할 수 있습니다.

프리드리히 감사합니다


답변

다음과 같은 방식으로 사용할 수 있습니다.

//! Define:
#define F_NUM 3
int (*pFunctions[F_NUM])(void * arg);

//! Initialise:
int someFunction(void * arg) {
    int a= *((int*)arg);
    return a*a;
}

pFunctions[0]= someFunction;

//! Use:
int someMethod(int idx, void * arg, int * result) {
    int done= 0;
    if (idx < F_NUM && pFunctions[idx] != NULL) {
        *result= pFunctions[idx](arg);
        done= 1;
    }
    return done;
}

int x= 2;
int z= 0;
someMethod(0, (void*)&x, &z);
assert(z == 4);


답변

위의 응답에 대한 짧고 간단한 복사 및 붙여 넣기 코드 예제 여야합니다. 잘하면 이것이 도움이됩니다.

#include <iostream>
using namespace std;

#define DBG_PRINT(x) do { std::printf("Line:%-4d" "  %15s = %-10d\n", __LINE__, #x, x); } while(0);

void F0(){ printf("Print F%d\n", 0); }
void F1(){ printf("Print F%d\n", 1); }
void F2(){ printf("Print F%d\n", 2); }
void F3(){ printf("Print F%d\n", 3); }
void F4(){ printf("Print F%d\n", 4); }
void (*fArrVoid[N_FUNC])() = {F0, F1, F2, F3, F4};

int Sum(int a, int b){ return(a+b); }
int Sub(int a, int b){ return(a-b); }
int Mul(int a, int b){ return(a*b); }
int Div(int a, int b){ return(a/b); }
int (*fArrArgs[4])(int a, int b) = {Sum, Sub, Mul, Div};

int main(){
    for(int i = 0; i < 5; i++)  (*fArrVoid[i])();
    printf("\n");

    DBG_PRINT((*fArrArgs[0])(3,2))
    DBG_PRINT((*fArrArgs[1])(3,2))
    DBG_PRINT((*fArrArgs[2])(3,2))
    DBG_PRINT((*fArrArgs[3])(3,2))

    return(0);
}