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