Подтвердить что ты не робот

Указатель функции как член структуры C

У меня есть структура следующим образом, с указателем на функцию с названием "длина", которая вернет длину члена символов.

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

У меня есть функция, возвращающая длину символов из указателя на PString:

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

У меня есть функция initializeString(), которая возвращает указатель на PString:

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

Понятно, что я делаю что-то очень не так с моими указателями здесь, потому что строка str->length = &length вызывает в моем отладчике сигнал EXC_BAD_ACCESS, как и `return strlen (self- > chars). Кто-нибудь знает о этой проблеме?

Я специально хочу, чтобы функция initializeString() возвращала указатель на PString, а функция length использовала указатель на PString в качестве входных данных. Это всего лишь эксперимент по реализации элементарной объектно-ориентированной системы на C, но у меня нет большого опыта работы с указателями. Спасибо за любую помощь, которую вы можете мне дать.

4b9b3361

Ответ 1

Выделите память для хранения символов.

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

Ответ 2

Моя догадка заключается в том, что частью вашей проблемы являются списки параметров, не соответствующие.

int (* length)();

и

int length(PString * self)

не совпадают. Это должно быть int (* length)(PString *);.

... woah, это Джон!

Изменить: и, как указано ниже, ваш указатель структуры никогда не будет указывать на что-либо. То, как вы это делаете, будет работать, только если вы объявляете простую структуру, а не указатель.

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

Ответ 3

Указатель str никогда не выделяется. Он должен быть malloc 'd перед использованием.

Ответ 4

Может быть, мне что-то не хватает, но выделили ли вы какую-либо память для этой PString, прежде чем вы ее получили?

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

Ответ 5

Вы также можете использовать "void *" (указатель void) для отправки адреса функции.

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

Вывод:

Length: 5