#ifndef (* destroy) (* match) - PullRequest
       0

#ifndef (* destroy) (* match)

1 голос
/ 16 февраля 2011

Может кто-нибудь объяснить определение #indef, void (* destroy) (void * data)

int (*match)(const void *key1,const void *key2)

в следующем:

#ifndef LIST_H
#define LIST_H
#include <stdio.h>

typedef struct _ListElmt{

void                *data;
struct ListElmt     *next;

} ListElmt;
typedef struct _List{

int                 size;
int                 (*match)(const void *key1, const void *key2);
void                (*destroy)(void *data);

ListElmt             *head;
ListElmt             *tail;

} List;

void list_init(List *list, void (*destroy)(void *data));

void list_destroy(List *list);

int list_ins_next(List *list, ListElmt *element, const void *data);

int list_rem_next(List *list, ListElmt *element, void **data);

int list_size(const List *list);

ListElmt *list_head(const List *list);

ListElmt *list_tail(const List *list);

int list_is_head(const ListElmt *element);

int list_is_tail(const ListElmt *element);

void *list_data(const ListElmt *element);

ListElmt *list_next(const ListElmt *element);
#endif

Ответы [ 2 ]

2 голосов
/ 16 февраля 2011

Строка #ifndef является началом защиты заголовка .Это предотвращает включение заголовка дважды в одном и том же контексте.

Строка void (*destroy)(void *data) определяет указатель на функцию .Это указатель на функцию, которая принимает void* в качестве аргумента и возвращает void, а имя указателя destroy.

Переменная match также является указателем функции.

1 голос
/ 16 февраля 2011

Директива #ifndef является частью include guard , фрагмента кода C, найденного практически во всех заголовочных файлах, который предотвращает многократное включение. Общая структура заголовочного файла C:

#ifndef Some_Symbol
#define Some_Symbol

/* ... body of the header file ... */

#endif

Эти строки, начинающиеся с хэшей, называются директив препроцессора и инструктируют препроцессор вносить изменения в этот код, прежде чем компилятор начнет переводить его в код. Директива #ifndef расшифровывается как «IF Not DEFined» и является своего рода оператором if времени компиляции. Значение вышеприведенного кода

if (I haven't seen the symbol "Some_Symbol") {
    Define the symbol "Some_Symbol", so now I have seen it;
    Compile the body of the header file;
}

(Это недопустимый C, но он все понял).

Идея, лежащая в основе этой структуры, заключается в том, что если вы #include дважды используете один и тот же файл, то в первый раз, поскольку компилятор не показался с заданным символом, он включается и включает содержимое заголовка. Однако на любой последующей итерации компилятор будет видеть символ, и поэтому он не будет пытаться вставить тот же код во второй раз.

Что касается вашей загадочной линии

void (*destroy)(void *data);

Это указатель на функцию , который указывает на функцию, которая принимает void * и возвращает void. Например, он может указывать на функцию

void FreeMyData(void *data);

или

void FreeMyStringData(void *data);

Хотя нет

int printf(const char* fmtString, ...);

Интуиция за этой функцией заключается в том, что если вы создаете общий связанный список в C, список должен знать какой-то способ, которым он должен располагать элементами, хранящимися в списке, когда список восстанавливается. Для этого пользователь должен указать функцию, определяющую, как эта работа должна быть выполнена. Это хранится в указателе destroy, поэтому, когда список освобождается, вы можете сделать что-то вроде этого:

myList->destroy(myUserData);

Это позволяет автору списка обеспечить очистку памяти, даже если она не знает, какие данные будут там. Она может просто предположить, что пользователь предоставит правильный код очистки, а затем просто указать, когда в списке очистки должен выполняться код очистки.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...