Директива #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);
Это позволяет автору списка обеспечить очистку памяти, даже если она не знает, какие данные будут там. Она может просто предположить, что пользователь предоставит правильный код очистки, а затем просто указать, когда в списке очистки должен выполняться код очистки.
Надеюсь, это поможет!