web-dev-qa-db-ger.com

Funktionszeiger als Member einer C-Struktur

Ich habe eine struct wie folgt, mit einem Zeiger auf eine Funktion namens "length", die die Länge des chars-Mitglieds zurückgibt.

typedef struct pstring_t {
    char * chars;
    int (* length)();
} PString;

Ich habe eine Funktion, um die Länge der Zeichen von einem Zeiger auf einen PString zurückzugeben:

int length(PString * self) {
    return strlen(self->chars);
}

Ich habe eine Funktion initializeString (), die einen Zeiger auf einen PString zurückgibt:

PString * initializeString() {
    PString *str;
    str->length = &length;
    return str;
}

Es ist klar, dass ich mit meinen Zeigern hier etwas sehr falsch mache, weil die str->length = &length-Zeile ein EXC_BAD_ACCESS-Signal in meinem Debugger verursacht, ebenso wie `return strlen (self> zeichen). Hat jemand Einblick in dieses Problem?

Ich möchte insbesondere, dass die Funktion initializeString () einen Zeiger auf einen PString und die Längenfunktion zurückgeben kann, um einen Zeiger auf einen PString als Eingabe zu verwenden. Dies ist nur ein Experiment, um ein rudimentäres objektorientiertes System in C zu implementieren, aber ich habe nicht viel Erfahrung im Umgang mit Zeigern. Danke für jede Hilfe, die Sie mir geben können.

40

Weisen Sie Speicher für Zeichen zu.

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

typedef struct PString {
        char *chars;
        int (*length)();
} PString;

int length(PString *self) {
    return strlen(self->chars);
}

PString *initializeString(int n) {
    PString *str = malloc(sizeof(PString));

    str->chars = malloc(sizeof(char) * n);
    str->length = length;

    str[0] = '\0'; //add a null terminator in case the string is used before any other initialization.

    return str;
}

int main() {
    PString *p = initializeString(30);
    strcpy(p->chars, "Hello");
    printf("\n%d", p->length(p));
    return 0;
}
54
adatapost

Meine Vermutung ist, dass ein Teil Ihres Problems darin besteht, dass die Parameterlisten nicht übereinstimmen.

int (* length)();

und

int length(PString * self)

sind nicht das Gleiche. Es sollte int (* length)(PString *); sein.

... woah, es ist Jon!

Edit : und, wie unten erwähnt, ist Ihr Strukturzeiger nie auf irgendetwas gesetzt. Die Art und Weise, wie Sie dies tun, funktioniert nur, wenn Sie eine einfache Struktur und keinen Zeiger deklarieren.

str = (PString *)malloc(sizeof(PString));
6
jtbandes

Der Zeiger str wird niemals zugewiesen. Es sollte malloc'd vor der Verwendung sein.

4
jgottula

Vielleicht fehlt mir hier etwas, aber haben Sie dem PString Speicherplatz zugewiesen, bevor Sie darauf zugegriffen haben?

PString * initializeString() {
    PString *str;
    str = (PString *) malloc(sizeof(PString));
    str->length = &length;
    return str;
}
4
EdH

Sie können auch "void *" (void pointer) verwenden, um eine Adresse an die Funktion zu senden.

typedef struct pstring_t {
    char * chars;
    int(*length)(void*);
} PString;

int length(void* self) {
    return strlen(((PString*)self)->chars);
}

PString initializeString() {
    PString str;
    str.length = &length;
    return str;
}

int main()
{
    PString p = initializeString();

    p.chars = "Hello";

    printf("Length: %i\n", p.length(&p));

    return 0;
}

Ausgabe:

Length: 5
0
ontech7