Hoe kan ik een array van functiewijzers gebruiken?

Hoe moet ik een array van functiewijzers in C gebruiken?

Hoe kan ik ze initialiseren?


Antwoord 1, autoriteit 100%

Je hebt hier (Array of Function pointers)een goed voorbeeld , met de syntaxis gedetailleerd.

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() */
[...]

Om een van die functiewijzers aan te roepen:

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

Antwoord 2, autoriteit 24%

De bovenstaande antwoorden kunnen u misschien helpen, maar u wilt misschien ook weten hoe u een reeks functiewijzers gebruikt.

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

U kunt alleen de adressen van functies met hetzelfde retourtype en dezelfde argumenttypes en geen argumenten toewijzen aan een enkele functieaanwijzerarray.

Je kunt ook argumenten zoals hieronder doorgeven als alle bovenstaande functies hetzelfde aantal argumenten van hetzelfde type hebben.

 (*func_ptr[option])(argu1);

Opmerking: hier in de array zal de nummering van de functiewijzers beginnen bij 0, net als in algemene arrays. Dus in bovenstaand voorbeeld kan fun1worden aangeroepen als option=0, fun2kan worden aangeroepen als option=1 en fun3kan worden aangeroepen als option= 2.


Antwoord 3, autoriteit 4%

Zo kun je het gebruiken:

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

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

Hoofd.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;
}

Ik hoop dat dit helpt bij het begrijpen van Function Pointer.


Antwoord 4, Autoriteit 3%

Dit “antwoord” is meer een addendum bij het antwoord van Vonc; Alleen op te merken dat de syntaxis kan worden vereenvoudigd via een typedeof en de geaggregeerde initialisatie kan worden gebruikt:

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

Antwoord 5

Oh, er zijn tonnen voorbeeld. Kijk maar eens naar alles binnen Glib of GTK.
Je kunt het werk van functiewijzers allemaal helemaal zien.

Hier b.g de initialisatie van de GTK_BUTTON-dingen.


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;

en in gtkobject.h u vindt de volgende verklaringen:


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

Het (*set_arg) spul is een verwijzing naar een functie en dit kan bijvoorbeeld een andere implementatie in een afgeleide klasse worden toegewezen.

Vaak zie je zoiets als dit

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

Je kunt dus op naam in de tabel komen en de “geassocieerde” functie aanroepen.

Of misschien gebruikt u een hashtabel waarin u de functie plaatst en deze “op naam” noemt.

Met vriendelijke groet

Friedrich


Antwoord 6

Kan het op de volgende manier gebruiken:

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

Antwoord 7

Dit moet een korte & eenvoudig kopiëren & plak stukje code voorbeeld van de bovenstaande reacties. Hopelijk helpt dit.

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

Antwoord 8

De eenvoudigste oplossing is om het adres van de uiteindelijke vector die je wilt, op te geven en deze binnen de functie aan te passen.

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
}

Antwoord 9

Hier is een eenvoudiger voorbeeld van hoe u het moet doen:

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
}

Alle functies die in de array zijn opgeslagen, moeten dezelfde handtekening hebben. Dit betekent gewoon dat ze hetzelfde type (b.v. int) moeten retourneren en dezelfde argumenten hebben (een enkele intin het bovenstaande voorbeeld).


In C++ kunt u hetzelfde doen met Static Klasse-methoden (maar geen instantiemethoden). U kunt bijvoorbeeld MyClass::myStaticMethodin de bovenstaande array, maar niet MyClass::myInstanceMethodnoch instance.myInstanceMethod:

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

Antwoord 10

Deze vraag is al beantwoord met zeer goede voorbeelden. Het enige voorbeeld dat mogelijk ontbreekt, is een is waar de functies aanwijzingen kunnen retourneren. Ik schreef hier een ander voorbeeld en voegde veel opmerkingen toe, in het geval iemand het nuttig vindt:

#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;
}

Antwoord 11

Dit eenvoudige voorbeeld voor een multidimensionale array met functiewijzers”:

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

Antwoord 12

#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;
}

Other episodes