it-swarm.com.de

C - Funktion innerhalb von struct

Ich versuche, eine Funktion innerhalb einer Struktur zu erstellen, bisher habe ich diesen Code:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;

        pno AddClient() 

        {
            /* code */
        }

};

int main()
{

    client_t client;

    //code ..

    client.AddClient();

}

Fehler: client.h: 24: 2: fehler: erwartet ':', ',', ';', '}' oder 'Attribut 'vor' {'Token.

Welches ist der richtige Weg, um es zu tun?

67
xRed

Dies ist nicht direkt möglich, aber Sie können dasselbe mit Funktionszeigern und der expliziten Übergabe des Parameters "this" emulieren:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;

        pno (*AddClient)(client_t *);    
};

pno client_t_AddClient(client_t *self) { /* code */ }

int main()
{

    client_t client;
    client.AddClient = client_t_AddClient; // probably really done in some init fn

    //code ..

    client.AddClient(&client);

}

Es stellt sich jedoch heraus, dass Sie dadurch nicht wirklich viel Geld verdienen. Daher werden nicht viele C-APIs in diesem Stil implementiert, da Sie auch einfach Ihre externe Funktion aufrufen und die Instanz übergeben können.

91
FatalError

Wie bereits erwähnt, ist das Einbetten von Funktionszeigern direkt in Ihre Struktur in der Regel für spezielle Zwecke reserviert, z. B. für eine Rückruffunktion.

Was Sie wahrscheinlich wollen, ist eher eine virtuelle Methodentabelle.

typedef struct client_ops_t client_ops_t;
typedef struct client_t client_t, *pno;

struct client_t {
    /* ... */
    client_ops_t *ops;
};

struct client_ops_t {
    pno (*AddClient)(client_t *);
    pno (*RemoveClient)(client_t *);
};

pno AddClient (client_t *client) { return client->ops->AddClient(client); }
pno RemoveClient (client_t *client) { return client->ops->RemoveClient(client); }

Wenn Sie jetzt weitere Operationen hinzufügen, ändert sich die Größe der Struktur client_t Nicht. Diese Art von Flexibilität ist nur dann sinnvoll, wenn Sie verschiedene Arten von Clients definieren müssen oder Benutzern Ihrer client_t - Schnittstelle ermöglichen möchten, das Verhalten der Vorgänge zu verbessern.

Diese Art von Struktur erscheint in echtem Code. Die OpenSSL-BIO-Schicht sieht ähnlich aus, und auch UNIX-Gerätetreiber-Schnittstellen haben eine Schicht wie diese.

21
jxh

Dies funktioniert nur in C++. Funktionen in Strukturen sind kein Merkmal von C.

Gleiches gilt für Ihren Client.AddClient (); call ... Dies ist ein Aufruf für eine Member-Funktion, die objektorientierte Programmierung ist, d. h. C++.

Konvertieren Sie Ihre Quelle in eine CPP-Datei und stellen Sie sicher, dass Sie entsprechend kompilieren.

Wenn Sie sich an C halten müssen, ist der folgende Code (sozusagen) das Äquivalent:

typedef struct client_t client_t, *pno;
struct client_t
{
        pid_t pid;
        char password[TAM_MAX]; // -> 50 chars
        pno next;

};


pno AddClient(pno *pclient) 
{
    /* code */
}


int main()
{

    client_t client;

    //code ..

    AddClient(client);

}
12
QSQ

Wie wäre es damit?

#include <stdio.h>

typedef struct hello {
    int (*someFunction)();
} hello;

int foo() {
    return 0;
}

hello Hello() {
    struct hello aHello;
    aHello.someFunction = &foo;
    return aHello;
}

int main()
{
    struct hello aHello = Hello();
    printf("Print hello: %d\n", aHello.someFunction());

    return 0;
} 
10
rogal

Sie versuchen, Code gemäß struct zu gruppieren. Die C-Gruppierung erfolgt nach Datei. Sie fügen alle Funktionen und internen Variablen in einen Header oder eine Header- und eine Objektdatei ".o" ein, die aus einer c-Quelldatei kompiliert wurde.

Für ein C-Programm, das keine objektorientierte Sprache ist, ist es nicht erforderlich, die Objektorientierung von Grund auf neu zu erfinden.

Ich habe das schon mal gesehen. Es ist eine seltsame Sache. Einige von ihnen haben eine Abneigung dagegen, ein Objekt, das sie ändern möchten, in eine Funktion umzuwandeln, um es zu ändern, auch wenn dies die Standardmethode ist.

Ich beschuldige C++, weil es die Tatsache verbirgt, dass das Klassenobjekt immer der erste Parameter in einer Mitgliedsfunktion ist, aber es ist versteckt. Es sieht also so aus, als würde das Objekt nicht an die Funktion übergeben, obwohl dies der Fall ist.

Client.addClient(Client& c); // addClient first parameter is actually 
                             // "this", a pointer to the Client object.

C ist flexibel und kann Dinge als Referenz übergeben.

Eine C-Funktion gibt oft nur ein Statusbyte oder int zurück und das wird oft ignoriert. In Ihrem Fall könnte eine ordnungsgemäße Form sein

 err = addClient( container_t  cnt, client_t c);
 if ( err != 0 )
   { fprintf(stderr, "could not add client (%d) \n", err ); 

addClient würde sich in Client.h oder Client.c befinden

4
Chris Reid