Functiewijzer als lid van een C-struct

Ik heb een struct als volgt, met een pointer naar een functie genaamd “length” die de lengte van het chars-lid zal retourneren.

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

Ik heb een functie om de lengte van de karakters van een pointer naar een PSstring te retourneren:

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

Ik heb een functie initializeString() die een pointer naar een PString terugstuurt:

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

Het is duidelijk dat ik hier iets heel erg verkeerd doe met mijn pointers, omdat de regel str->length = &lengtheen EXC_BAD_ACCESS-signaal in mijn debugger veroorzaakt, net als `return strlen (zelf->chars). Heeft iemand enig inzicht in dit probleem?

Ik wil specifiek dat de functie initializeString() een pointer naar een PString retourneert, en de lengtefunctie om een ​​pointer naar een PString als invoer te gebruiken. Dit is slechts een experiment bij het implementeren van een rudimentair objectgeoriënteerd systeem in C, maar ik heb niet veel ervaring met het direct omgaan met pointers. Bedankt voor alle hulp die je me kunt geven.


Antwoord 1, autoriteit 100%

Wijs geheugen toe om tekens op te slaan.

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

Antwoord 2, autoriteit 9%

Ik vermoed dat een deel van je probleem is dat de parameterlijsten niet overeenkomen.

int (* length)();

en

int length(PString * self)

zijn niet hetzelfde. Het moet int (* length)(PString *);zijn.

…woah, het is Jon!

Bewerken: en, zoals hieronder vermeld, is je struct-aanwijzer nooit ingesteld om naar iets te verwijzen. De manier waarop je het doet, zou alleen werken als je een duidelijke struct aangeeft, geen pointer.

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

Antwoord 3, autoriteit 8%

Misschien mis ik hier iets, maar heb je geheugen toegewezen aan die PSstring voordat je er toegang toe kreeg?

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

Antwoord 4, autoriteit 5%

De aanwijzer strwordt nooit toegewezen. Het moet voor gebruik malloc‘d zijn.


Antwoord 5

U kunt ook “void*” (void pointer) gebruiken om een ​​adres naar de functie te sturen.

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

Uitvoer:

Length: 5

Other episodes