source

함수 포인터의 배열을 사용하려면 어떻게 해야 합니까?

goodcode 2022. 8. 11. 22:19
반응형

함수 포인터의 배열을 사용하려면 어떻게 해야 합니까?

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부터 시작됩니다.위의 예에서는fun1옵션=0인 경우 호출할 수 있습니다.fun2option=1 이면 호출할 수 있습니다.fun3옵션=2인 경우 호출할 수 있습니다.

다음은 그 방법의 간단한 예입니다.

jump_table.c

int func1(int arg)  { return arg + 1; }
int func2(int arg)  { return arg + 2; }
int func3(int arg)  { return arg + 3; }
int func4(int arg)  { return arg + 4; }
int func5(int arg)  { return arg + 5; }
int func6(int arg)  { return arg + 6; }
int func7(int arg)  { return arg + 7; }
int func8(int arg)  { return arg + 8; }
int func9(int arg)  { return arg + 9; }
int func10(int arg) { return arg + 10; }

int (*jump_table[10])(int) = { func1, func2, func3, func4, func5, 
                               func6, func7, func8, func9, func10 };
    
int main(void) {
  int index = 2;
  int argument = 42;
  int result = (*jump_table[index])(argument);
  // result is 45
}

어레이에 저장된 모든 함수는 동일한 시그니처를 가져야 합니다.이는 단순히 동일한 유형(예: 같은 유형)을 반환해야 함을 의미합니다.int같은 인수(단일)를 가지고 있습니다.int를 참조해 주세요).


C++ 에서는, 스태틱클래스 메서드(인스턴스 메서드는 제외)에서도 같은 처리를 실시할 수 있습니다.예를 들어,MyClass::myStaticMethod상기의 배열에 있지만, 그렇지 않다MyClass::myInstanceMethod도 아니다instance.myInstanceMethod:

class MyClass {
public:
  static int myStaticMethod(int foo)   { return foo + 17; }
  int        myInstanceMethod(int bar) { return bar + 17; }
}

MyClass instance;

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

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");
}

메인.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; }

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

//! 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);

가장 간단한 해결책은 원하는 최종 벡터의 주소를 지정하고 함수 내에서 수정하는 것입니다.

void calculation(double result[] ){  //do the calculation on result

   result[0] = 10+5;
   result[1] = 10 +6;
   .....
}

int main(){

    double result[10] = {0}; //this is the vector of the results

    calculation(result);  //this will modify result
}

이것은, 상기의 회답의 간단한 카피&페이스트 코드의 예입니다.이게 도움이 됐으면 좋겠다.

#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);
}
#include <iostream>
using namespace std;
    
int sum (int , int);
int prod (int , int);
    
int main()
{
    int (*p[2])(int , int ) = {sum,prod};
    
    cout << (*p[0])(2,3) << endl;
    cout << (*p[1])(2,3) << endl;
}
    
int sum (int a , int b)
{
    return a+b;
}
    
int prod (int a, int b)
{
    return a*b;
}

오, 표본이 매우 많다.그냥 glib 또는 gtk 합리적인 일은 무엇이나를 한번 봅시다.일에는 함수 포인터의 일 볼 수 있어요.

여기gtk_button 이것의 초기화 e.g.


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)는 것이 포인터와 이것이 어떤 파생 클래스에서 다른 구현이 할당될 e.g 수 있다.

당신은 종종 이런 것을 볼 수 있습니다.

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},
...

따라서 테이블에 이름을 입력하여 "관련" 함수를 호출할 수 있습니다.

또는 해시 테이블을 사용하여 함수를 "이름으로"라고 부릅니다.

★★★★★★★★★★★★★에 대하여

이 질문에는 이미 아주 좋은 예시로 답변이 되어 있습니다.누락될 수 있는 유일한 예는 함수가 포인터를 반환하는 예입니다.다른 예시를 쓰고 도움이 될 수 있도록 많은 코멘트를 추가했습니다.

#include <stdio.h>

char * func1(char *a) {
    *a = 'b';
    return a;
}

char * func2(char *a) {
    *a = 'c';
    return a;
}

int main() {
    char a = 'a';
    /* declare array of function pointers
     * the function pointer types are char * name(char *)
     * A pointer to this type of function would be just
     * put * before name, and parenthesis around *name:
     *   char * (*name)(char *)
     * An array of these pointers is the same with [x]
     */
    char * (*functions[2])(char *) = {func1, func2};
    printf("%c, ", a);
    /* the functions return a pointer, so I need to deference pointer
     * Thats why the * in front of the parenthesis (in case it confused you)
     */
    printf("%c, ", *(*functions[0])(&a)); 
    printf("%c\n", *(*functions[1])(&a));

    a = 'a';
    /* creating 'name' for a function pointer type
     * funcp is equivalent to type char *(*funcname)(char *)
     */
    typedef char *(*funcp)(char *);
    /* Now the declaration of the array of function pointers
     * becomes easier
     */
    funcp functions2[2] = {func1, func2};

    printf("%c, ", a);
    printf("%c, ", *(*functions2[0])(&a));
    printf("%c\n", *(*functions2[1])(&a));

    return 0;
}

함수 포인터가 있는 다차원 배열의 간단한 예":

void one( int a, int b){    printf(" \n[ ONE ]  a =  %d   b = %d",a,b);}
void two( int a, int b){    printf(" \n[ TWO ]  a =  %d   b = %d",a,b);}
void three( int a, int b){    printf("\n [ THREE ]  a =  %d   b = %d",a,b);}
void four( int a, int b){    printf(" \n[ FOUR ]  a =  %d   b = %d",a,b);}
void five( int a, int b){    printf(" \n [ FIVE ]  a =  %d   b = %d",a,b);}
void(*p[2][2])(int,int)   ;
int main()
{
    int i,j;
    printf("multidimensional array with function pointers\n");

    p[0][0] = one;    p[0][1] = two;    p[1][0] = three;    p[1][1] = four;
    for (  i  = 1 ; i >=0; i--)
        for (  j  = 0 ; j <2; j++)
            (*p[i][j])( (i, i*j);
    return 0;
}

언급URL : https://stackoverflow.com/questions/252748/how-can-i-use-an-array-of-function-pointers

반응형