Wie kann ich ein Array von Funktionszeigern verwenden?

Lesezeit: 7 Minuten

Wie sollte ich ein Array von Funktionszeigern in C verwenden?

Wie kann ich sie initialisieren?

Benutzeravatar von VonC
VonC

Sie haben ein gutes Beispiel hier (Array von Funktionszeigern)mit dem Syntax detailliert.

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

So rufen Sie einen dieser Funktionszeiger auf:

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

  • Gute Antwort – Sie sollten sie jedoch erweitern, um zu zeigen, wie eine der Funktionen aufgerufen wird.

    – Jonathan Leffler

    31. Oktober 2008 um 19:30 Uhr

  • @crucifiedsoul “the C Programming Language”, geschrieben von Brian Kernighan und Dennis Ritchie? Es könnte sein, aber ich hatte es nicht als Referenz, als ich vor dreieinhalb Jahren die Antwort schrieb. Ich weiß es nicht.

    – VonC

    30. März 2012 um 1:51 Uhr

  • Ich möchte hinzufügen, dass Sie p mit initialisieren können (*p[4]) (int, int) {sum,substract,mul,div}

    – Jiggunjer

    7. Juli 2015 um 8:04 Uhr

  • @VonC: tolle Antwort. +1 für die Links.

    – Destruktor

    9. Juli 2015 um 17:04 Uhr

  • @WilliamMartens Gern geschehen. Ich bin immer überrascht, wenn ein Link, den ich vor über 12 Jahren benutzt habe, immer noch funktioniert!

    – VonC

    17. Februar 2021 um 9:33 Uhr


Benutzeravatar von Manoj Doubts
Manoj Zweifel

Die obigen Antworten können Ihnen helfen, aber Sie möchten vielleicht auch wissen, wie man ein Array von Funktionszeigern verwendet.

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

Sie können nur die Adressen von Funktionen mit demselben Rückgabetyp und denselben Argumenttypen und derselben Anzahl von Argumenten einem einzigen Funktionszeigerarray zuweisen.

Sie können auch Argumente wie unten übergeben, wenn alle oben genannten Funktionen die gleiche Anzahl von Argumenten des gleichen Typs haben.

  (*func_ptr[option])(argu1);

Hinweis: Hier im Array beginnt die Nummerierung der Funktionszeiger wie bei allgemeinen Arrays bei 0. Also im obigen Beispiel fun1 kann aufgerufen werden, wenn Option=0, fun2 kann aufgerufen werden, wenn Option=1 und fun3 kann aufgerufen werden, wenn Option=2.

  • Auch für diese kleine Demo sollten Sie den Eingabewert überprüfen, da der Code auf einen Neuling abzielt … 🙂

    – Philho

    31. Oktober 2008 um 6:53 Uhr

  • Vergessen Sie nicht #include ganz oben für Neulinge wie mich

    – www-0av-Com

    31. Januar um 13:22 Uhr

Benutzeravatar von Rasmi Ranjan Nayak
Rasmi Ranjan Nayak

So können Sie es verwenden:

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

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

Ich hoffe, das hilft zum Verständnis Function Pointer.

  • Zeile 15 von Main.c sollte für (i = 0; i < 5; i++) stehen, richtig?

    – Benutzer3116936

    14. Januar 2017 um 3:40 Uhr

  • Warum haben Sie den fp-Enumerator deklariert?

    – Pfeil

    18. September 2017 um 12:50 Uhr

  • @Arrrow: Ich glaube, ich habe einen Teil des Legacy-Codes gesehen, wo sie es auf diese Weise gemacht haben … Und es sieht sehr schön aus. Einfach entfernen f1, f2 ... und anstelle von dann ‘writefile, readfromfile …’ eingeben … es wird redabler

    – Rasmi Ranjan Nayak

    13. November 2017 um 21:06 Uhr


Diese “Antwort” ist eher ein Nachtrag zur Antwort von VonC; Beachten Sie nur, dass die Syntax über eine Typedef vereinfacht werden kann und die Aggregatinitialisierung verwendet werden kann:

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

Benutzeravatar von Alex Hajnal
Alex Hajnal

Hier ist ein einfacheres Beispiel, wie es geht:

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 im Array gespeicherten Funktionen müssen die gleiche Signatur haben. Das bedeutet einfach, dass sie denselben Typ zurückgeben müssen (z int) und haben die gleichen Argumente (eine einzige int im Beispiel oben).


In C++ können Sie dasselbe mit tun statisch Klassenmethoden (aber keine Instanzmethoden). Sie könnten zum Beispiel verwenden MyClass::myStaticMethod im Array oben, aber nicht MyClass::myInstanceMethod Noch instance.myInstanceMethod:

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

MyClass instance;

Benutzeravatar von Jonathan Leffler
Jonathan Leffler

Oh, es gibt Unmengen von Beispielen. Schauen Sie sich einfach irgendetwas in glib oder gtk an. Dort können Sie die Arbeit von Funktionszeigern in Arbeit sehen.

Hier zB die Initialisierung des gtk_button Zeugs.


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;

Und in gtkobject.h finden Sie die folgenden Deklarationen:


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

Das Zeug (*set_arg) ist ein Zeiger auf eine Funktion und dieser kann zB eine andere Implementierung in einer abgeleiteten Klasse zugewiesen werden.

Oft sieht man so etwas

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

So können Sie über den Namen in die Tabelle greifen und die “zugehörige” Funktion aufrufen.

Oder vielleicht verwenden Sie eine Hash-Tabelle, in die Sie die Funktion einfügen und sie “nach Namen” nennen.

Grüße

Friedrich

Benutzeravatar von Peter Hirt
Peter Hirt

Kann es so verwenden:

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

1425650cookie-checkWie kann ich ein Array von Funktionszeigern verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy