Funktionszeiger als Mitglied einer C-Struktur

Lesezeit: 5 Minuten

Ich habe eine Struktur wie folgt, mit einem Zeiger auf eine Funktion namens “Länge”, 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 hier mit meinen Hinweisen etwas sehr falsch mache, denn die str->length = &length line verursacht ein EXC_BAD_ACCESS-Signal in meinem Debugger, ebenso wie `return strlen(self->chars). Hat jemand irgendwelche Einblicke in dieses Problem?

Ich möchte insbesondere in der Lage sein, dass die Funktion initializeString() einen Zeiger auf einen PString zurückgibt und die Funktion length einen Zeiger auf einen PString als Eingabe verwendet. Dies ist nur ein Experiment zur Implementierung eines rudimentären objektorientierten Systems in C, aber ich habe nicht viel Erfahrung im direkten Umgang mit Zeigern. Danke für jede Hilfe, die Sie mir geben können.

  • Obwohl Sie sagen, dass Sie ausdrücklich einen Zeiger zurückgeben möchten. In diesem Fall ist es viel besser, eine Struktur selbst zurückzugeben. Es ist eine billig zu kopierende Struktur, und es besteht keine Notwendigkeit für eine schwere Heap-Zuweisung. String-Objekte sind wertbasiert: Sie haben keine Identität (Adresse), aber ihre Gleichheit basiert auf ihrem Inhalt. Irgendwie könnten Sie dieses Gefühl der Unterscheidung auch in Ihrem OOP-System haben.

    – Johannes Schaub – litb

    29. August 2009 um 16:41 Uhr

Benutzeravatar von KV Prajapati
KV Prajapati

Weisen Sie Speicher zu, um Zeichen zu halten.

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

typedef struct PString {
        char *chars;
        int (*length)(PString *self);
} 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->chars[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;
}

  • Gute Antwort! Frage: Ich muss free(p) anrufen, aber muss ich auch die Zeichen freigeben?

    – Jonathan Sterling

    29. August 2009 um 4:15 Uhr

  • Der Rückgabewert von muss nicht umgewandelt werden malloc in C. Außerdem sollten Sie initialisieren str->chars nachdem Sie es zugewiesen haben (dh. str->chars[0] = '\0';).

    – Café

    29. August 2009 um 4:41 Uhr

  • Führt den Funktionszeiger aus int (* length)() muss/nicht muss identifiziert werden PString * Parameter?

    – Ephemera

    9. Oktober 2013 um 23:26 Uhr


  • @ephemera hat einen Punkt. Sie müssen den vollständigen Prototyp der Funktion verwenden. Ich habe es versucht, ohne die Argumente der Funktion in der PString-Struktur anzugeben, und ich erhalte eine Fehlermeldung. Wenn ich schreibe int (* Länge)(PString *self);es funktioniert gut.

    – rbaleksandar

    8. November 2013 um 11:41 Uhr

  • Warum verwendet initializeString str->length = length; Anstatt von str->length = &length;? Wird es bei dieser Verwendung automatisch auf einen Zeiger reduziert?

    – Jakob Phillips

    22. November 2013 um 22:11 Uhr

Ich vermute, 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 sein int (* length)(PString *);.

… woah, es ist Jon!

Bearbeiten: und, wie unten erwähnt, ist Ihr Strukturzeiger niemals so eingestellt, dass er auf irgendetwas zeigt. Die Art und Weise, wie Sie es tun, würde nur funktionieren, wenn Sie eine einfache Struktur und keinen Zeiger deklarieren würden.

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

  • Vielen Dank, Jakob. Ich werde weitermachen und das versuchen.

    – Jonathan Sterling

    29. August 2009 um 3:53 Uhr

  • OK, strlen(self->chars) gibt mir noch EXC_BAD_ACCESS.

    – Jonathan Sterling

    29. August 2009 um 3:57 Uhr

Vielleicht fehlt mir hier etwas, aber haben Sie diesem PString Speicher zugewiesen, bevor Sie darauf zugegriffen haben?

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

  • Beenden Sie das Casting malloc bitte. In C muss man das nicht machen.

    – rassa45

    15. Juli 2018 um 23:37 Uhr

  • Gehen Sie besser mit allen Warnungen um.

    – Sam

    19. Mai 2020 um 4:58 Uhr

Der Zeiger str wird nie vergeben. Es sollte sein malloc‘d vor Gebrauch.

Benutzeravatar von ontech7
ontech7

Sie können auch “void*” (Void-Zeiger) 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

  • In acht nehmen! Dies führt zu undefiniertem Verhalten, da die Variable PString str; in initializeString() existiert nicht, wenn Sie über den Zeiger darauf zugreifen main().

    – Kupto

    28. März 2018 um 11:29 Uhr


  • Wie @Kupto erwähnte, da Sie dem Zeiger der Funktion keinen Speicher zuweisen, gibt es wirklich keine Aussage darüber, was Ihr Programm wirklich tun wird. Ich empfehle, die initializestring-Methode einen ptr an den Typ zurückgeben zu lassen und vor der Rückgabe den Zeiger der Funktion der Funktion zuzuweisen.

    – Larry

    18. Oktober 2019 um 23:41 Uhr

  • In acht nehmen! Dies führt zu undefiniertem Verhalten, da die Variable PString str; in initializeString() existiert nicht, wenn Sie über den Zeiger darauf zugreifen main().

    – Kupto

    28. März 2018 um 11:29 Uhr


  • Wie @Kupto erwähnte, da Sie dem Zeiger der Funktion keinen Speicher zuweisen, gibt es wirklich keine Aussage darüber, was Ihr Programm wirklich tun wird. Ich empfehle, die initializestring-Methode einen ptr an den Typ zurückgeben zu lassen und vor der Rückgabe den Zeiger der Funktion der Funktion zuzuweisen.

    – Larry

    18. Oktober 2019 um 23:41 Uhr

1412620cookie-checkFunktionszeiger als Mitglied einer C-Struktur

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

Privacy policy