Указатель на функцию как член структуры C - PullRequest
43 голосов
/ 29 августа 2009

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

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, но у меня нет большого опыта работы с указателями. Спасибо за любую помощь, вы можете дать мне.

Ответы [ 5 ]

58 голосов
/ 29 августа 2009

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

#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;
}
6 голосов
/ 29 августа 2009

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

int (* length)();

и

int length(PString * self)

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

... вау, это Джон!

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

str = (PString *)malloc(sizeof(PString));
4 голосов
/ 29 августа 2009

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

PString * initializeString() {
    PString *str;
    str = (PString *) malloc(sizeof(PString));
    str->length = &length;
    return str;
}
4 голосов
/ 29 августа 2009

Указатель str никогда не выделяется. Перед использованием malloc.

0 голосов
/ 10 сентября 2017

Вы также можете использовать «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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...