So definieren Sie ein Array von Funktionen in C

Lesezeit: 4 Minuten

Benutzer-Avatar
0x77D

Ich habe eine Struktur, die eine Deklaration wie diese enthält:

void (*functions[256])(void) //Array of 256 functions without arguments and return value

Und in einer anderen Funktion möchte ich es definieren, aber es gibt 256 Funktionen! Ich könnte so etwas machen:

struct.functions[0] = function0;
struct.functions[1] = function1;
struct.functions[2] = function2;

Und so weiter, aber das ist zu anstrengend, meine Frage, gibt es eine Möglichkeit, so etwas zu tun?

struct.functions = { function0, function1, function2, function3, ..., };

BEARBEITEN: Syntaxfehler korrigiert, wie von Chris Lutz gesagt.

Benutzer-Avatar
Chris Lutz

Ich habe eine Struktur, die eine Deklaration wie diese enthält:

Nein, tust du nicht. Das ist ein Syntaxfehler. Du schaust nach:

void (*functions[256])();

Welches ist ein Array von Funktionszeigern. Beachte das aber void func() ist keine “Funktion, die keine Argumente akzeptiert und nichts zurückgibt”. Es ist eine Funktion, die nicht spezifizierte Zahlen oder Arten von Argumenten akzeptiert und nichts zurückgibt. Wenn Sie “keine Argumente” wollen, brauchen Sie Folgendes:

void (*functions[256])(void);

In C++, void func() tut bedeuten “nimmt keine Argumente”, was einige Verwirrung stiftet (insbesondere da die Funktionalität, die C für void func() ist von zweifelhaftem Wert.)

So oder so, sollten Sie typedef Ihr Funktionszeiger. Dadurch wird der Code unendlich verständlicher und Sie haben nur eine Chance (bei der typedef) um die Syntax falsch zu machen:

typedef void (*func_type)(void);
// ...
func_type functions[256];

Wie auch immer, Sie können einem Array nicht zuweisen, aber Sie können ein Array initialisieren und die Daten kopieren:

static func_type functions[256] = { /* initializer */ };
memcpy(mystruct.functions, functions, sizeof(functions));

  • Beachten Sie nur, dass memcpy() gefährlich und nicht portierbar ist, da eine Struktur eine beliebige Anzahl von Füllbytes enthalten kann. Wenn Sie memcpy() wie hier gezeigt verwenden, müssen Sie sicherstellen, dass der Compiler kein Padding aktiviert hat. In der Regel durch assert(sizeof(the_struct.functions) == sizeof(functions)) oder ähnliches.

    – Ludin

    15. März 2011 um 10:33 Uhr

  • Das ist falsch. sizeof(some_struct) gibt die Größe der Struktur + alle notwendigen Polsterungen zurück. Siehe diese Frage zum Beispiel. Die Verwendung von memcpy oben ist richtig.

    – Matte

    15. März 2011 um 10:43 Uhr

  • ..und in diesem Fall die memcpy() wird sowieso nicht für Strukturen verwendet – es wird zum Kopieren von einem Array in ein anderes mit identischer Größe verwendet, was in Ordnung ist. Die Tatsache, dass das Zielarray ein Strukturmitglied ist, spielt keine Rolle.

    – Café

    15. März 2011 um 12:27 Uhr

  • Das hätte ich wohl anmerken sollen struct ist ein Schlüsselwort, daher ist es falsch, es als Variablennamen zu verwenden, selbst für Beispielcode, der niemals in die Nähe eines Compilers kommen wird.

    – Chris Lutz

    16. März 2011 um 0:06 Uhr

  • der Unterschied zwischen func() und func(void) ist nur eine Frage von C++ nicht von C, oder?

    – dhein

    21. Januar 2016 um 7:48 Uhr

Ich hatte das gleiche Problem, dies ist mein kleines Programm, um die Lösung zu testen. Es sieht ziemlich einfach aus, also dachte ich, ich würde es für zukünftige Besucher teilen.

#include <stdio.h>

int add(int a, int b) {
    return a+b;
}

int minus(int a, int b) {
    return a-b;
}

int multiply(int a, int b) {
    return a*b;
}

typedef int (*f)(int, int);                 //declare typdef

f func[3] = {&add, &minus, &multiply};      //make array func of type f,
                                            //the pointer to a function
int main() {
    int i;
    for (i = 0; i < 3; ++i) printf("%d\n", func[i](5, 4));
    return 0;
}

Benutzer-Avatar
TurtleToes

Sie können es dynamisch tun … Hier ist ein kleines Beispiel für ein dynamisches Funktionsarray, das mit malloc zugewiesen wurde …

#include <stdio.h>
#include <stdlib.h>

typedef void (*FOO_FUNC)(int x);

void a(int x)
{
    printf("Function a: %d\n", x);
}

void b(int x)
{
    printf("Function b: %d\n", x);
}

int main(int argc, char **argv)
{
    FOO_FUNC *pFoo = (FOO_FUNC *)malloc(sizeof(FOO_FUNC) * 2);
    pFoo[0] = &a;
    pFoo[1] = &b;

    pFoo[0](10);
    pFoo[1](20);

    return 0;
}

  • Mein schlechter … falscher Kontext zu dieser Diskussion … Stattdessen könnten Sie typedef verwenden, um den FOO_FUNC-Typ zu definieren, und dann ein FOO_FUNC-Array erstellen und die Namen als Initialisierer verwenden …

    – TurtleToes

    15. März 2011 um 12:43 Uhr


Aus der Spitze meines Kopfes und ungetestet.

// create array of pointers to functions
void (*functions[256])(void) = {&function0, &function1, &function2, ..., };

// copy pointers to struct
int i;
for (i = 0; i < 256; i++) struct.functions[i] = functions[i];

BEARBEITEN: Syntaxfehler korrigiert, wie von Chris Lutz gesagt.

Sie könnten dies tun, während Sie Ihre Struct-Instanz deklarieren:

function_structur fs = { struct_field1,
                         struct_field2,
                         {function0, function1, ..., function255},
                         struct_field3,
                         ... };

Sie können diese Abkürzung nicht verwenden, um Arrays zu initialisieren, nachdem das Array deklariert wurde: Wenn Sie dies tun müssen, müssen Sie es dynamisch tun (mithilfe einer Schleife, a memcpy oder etwas anderes).

Benutzer-Avatar
Syntagma

Wenn Sie wollen Post-Initialisieren Sie ein Array mit Formular wie {func1, func2, ...}kann dies auf folgende Weise (mit GCC) erreicht werden:

UPD (danke an Chris Lutz für Anmerkungen)

Definiere ein Makro wie folgt:

#define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))

Und übergeben Sie den Quellvektor mit Zusammengesetzte Literalewie folgt:

#include <string.h>
...
void (*functions[256])();
...
FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));

1364240cookie-checkSo definieren Sie ein Array von Funktionen in C

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

Privacy policy