Как использовать указатели на функции в C с использованием структур?

#c #struct #mingw #function-pointers

#c #структура #mingw #указатели на функции

Вопрос:

Я пытаюсь печатать время, используя указатели на функции и структуры. Это не дает никакой ошибки. Сначала это работает, но позже «Test.exe перестал бежать!».

Мои файлы: Random.c Random.h , Randomness.c Randomness.h, Test.c

Random.h

 struct RANDOM {
    char* date;
    char* (*Date) (struct RANDOM*);
    void (*Write) (struct RANDOM*);
};
typedef struct RANDOM* Random;

Random CreateRandom();
char* DateOfNow(const Random);
void WriteDate(const Random);
  

Random.c

 char* BringTime(){
    char* buff = malloc(sizeof(char)*100);
    time_t now = time(0);
    strftime(buff, 100, "%Y-%m-%d %H:%M",localtime(amp;now));

    return buff;
}

Random CreateRandom(){
    Random this;
    this = (Random) malloc(sizeof(struct RANDOM));  
    this->date = BringTime();

    return this;
}

char* DateOfNow(const Random this){
     return this->date;
}

void WriteDate(const Random this){
    printf("nn Date is: %s", this->date);
}
  

Randomness.h

 struct RANDOMNESS{
    Random super;
};

typedef struct RANDOMNESS* Randomness;

Randomness CreateRandomness();
  

Randomness.c

 Randomness CreateRandomness(){
    Randomness this;
    this = (Randomness)malloc(sizeof(struct RANDOMNESS));
    this->super = CreateRandom();

    return this;
}
  

Test.c

 int main() {

    Randomness rnd = CreateRandomness();
    printf("works till here");
    rnd->super->Write(rnd->super);
}
  

Вывод: работает до сих пор

После этого вывода он перестает работать «Test.exe перестал бежать».

Я попробовал printf("%p", rnd->super) , он дал мне адрес. Так что, возможно, есть проблема с Write(rnd->super) функцией.

Комментарии:

1. Выглядит нормально. Вероятно, проблема в несвязанной части кода. попробуйте valgrind (если предупреждения ничего не показывают).

2. Не скрывайте природу указателя за typedefs ( Random , Randomness ) . Это почти всегда затрудняет чтение и поддержку вашего кода. (И пример кода не является исключением.)

3. Вы никогда не инициализируете указатели на функции…

Ответ №1:

Вы должны назначить указатели на функции полям-членам в структуре:

 Random CreateRandom(){
    Random this;
    this = (Random) malloc(sizeof(struct RANDOM));  
    this->date = BringTime();
    // assign function pointer to actual functions
    this->Date = amp;DateOfNow; 
    this->Write = amp;WriteDate;

    return this;
}
  

Конечно, прототипы DateOfNow и WriteDate должны быть доступны до CreateRandom определения.

Примечание: вы можете написать this->Date = DateOfNow; (без amp; as amp; с идентификатором функции является излишним).

Ответ №2:

Ваша функция create является неполной:

 Random CreateRandom(){
    Random this;
    this = (Random) malloc(sizeof(struct RANDOM));  
    // Content of the memory is undefined!
    this->date = BringTime();
    // What about Write() and Date()? <<<======= ERROR IS HERE
    return this;
}

...

Randomness CreateRandomness(){
    Randomness this;
    this = (Randomness)malloc(sizeof(struct RANDOMNESS));
    this->super = CreateRandom();

    return this;
}

...

int main() {

    Randomness rnd = CreateRandomness();
    printf("works till here");
    rnd->super->Write(rnd->super); // << using unspecified values is undefined behaviour.
}
  

Вы присваиваете некоторое значение date , но не Date и Write .
Это означает, что у вас есть некоторая полезная ценность, rnd->super но содержимое rnd->super->Write не определено.

Если вы хотите использовать Create* функции как своего рода конструктор, вы также должны правильно установить указатели на функции.