我找到了一个用以下代码定义哈希表的标题:
#ifndef HASH_H
#define HASH_H
#define DEFINE_HASHTABLE(name, type, key, h_list, hashfunc)\
\
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
{\
unsigned long i;\
hashtable = (struct list*)malloc(size * sizeof (struct list_head));\
if (!hashtable)\
return -1;\
for (i = 0; i < size; i++)\
INIT_LIST_HEAD(&hashtable[i]);\
return 0;\
}\
\
static inline void hashtable_add(type *elem)\
{\
struct list_head *head = hashtable + hashfunc(elem->key);\
list_add(&elem->h_list, head);\
}\
\
static inline void hashtable_del(type *elem)\
{\
list_del(&elem->h_list);\
}\
\
static inline type * hashtable_find(unsigned long key)\
{\
type *elem;\
struct list_head *head = hashtable + hashfunc(key);\
\
list_for_each_entry(elem, head, h_list){\
if (elem->key == key) \
return elem; \
}\
return NULL;\
}
#endif /* _HASH_H */
我从未见过像这样的头文件。这种方式写头的好处是什么(我的意思是完整的宏)?它是关于通用性还是类似的东西?
答案 0 :(得分:2)
这是一种尝试确保所有散列函数调用都已授予其inline
请求的方法,即在执行散列表操作时减少函数调用的数量。
这只是一次尝试,它不能保证函数将被内联,但通过使它们static
至少有机会改进。有关此问题的大量讨论,请参阅this question,特别是@Christoph answer here。
请注意,每个C文件只能使用一次,因为没有&#34; unique&#34;部分添加到函数名称。
如果你这样做:
#include "hash.h"
DEFINE_HASHTABLE(foo, /* rest of arguments */);
DEFINE_HASHTABLE(bar, /* another bunch of args */);
您将收到编译错误,因为所有hashtable_
函数都将被定义两次。宏编写器可以通过将一组宏添加name
到所有定义的内容(变量和函数)来改进这一点。
即。这样:
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
应该成为:
static list *hashtable_ ##name;\
\
static int hashtable_ ##name ##_init(size_t size)\
依此类推(其中name
是第一个宏参数,即上面示例用法中的foo
和bar
。