任何人都可以解释#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
答案 0 :(得分:2)
#ifndef
行是header guard的开头。这可以防止在同一个上下文中包含两次标题。
第void (*destroy)(void *data)
行定义function pointer。这是一个指向函数的指针,该函数将void*
作为参数并返回void
,指针的名称为destroy
。
变量match
也是一个函数指针。
答案 1 :(得分:1)
#ifndef
指令是 include guard 的一部分,这是一个几乎在所有头文件中都可以找到的C代码,可以防止多次包含。 C头文件的一般结构是
#ifndef Some_Symbol
#define Some_Symbol
/* ... body of the header file ... */
#endif
这些以哈希开头的行称为预处理器direectives ,并指示预处理器在编译器开始将其转换为代码之前对此代码进行更改。 #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);
这允许列表作者确保清理内存,即使她不知道那里会有什么类型的数据。她可以假设用户将提供正确的清理代码,然后只需在列表清理时指定应该运行清理代码。
希望这有帮助!