在https://stackoverflow.com/questions/1138742/looking-for-a-good-hash-table-implementation-in-c里介绍了很多个相关的库。经过个人筛选,综合考虑执行效率、文档完善程度、支持的数据类型三方面,选择了uthash。
官方文档详见:http://troydhanson.github.io/uthash/userguide.html
*如果想当HashSet用,只需要value随便赋值即可
*如果只需要String类型的key和value,还可以考虑strmap
*之所以没选择python内置的libcfu(下载地址,官方文档),是因为它在Android的环境上编译时很多的问题。
简要范例 (详见官方文档)
1. 初始化
#include "uthash.h"
struct my_struct {
int id; // key
char name[10]; //value
UT_hash_handle hh; // 必须有,让这个结构体hashable
};
struct my_struct *users = NULL; // 重要,必须初始化为NULL
2. 添加
void add_user(int user_id, char *name) {
struct my_struct *s;
HASH_FIND_INT(users, &user_id, s);
if (s == NULL) {
s = (struct my_struct *)malloc(sizeof *s);
s->id = user_id;
HASH_ADD_INT(users, id, s); // id: key的名字
}
strcpy(s->name, name);
}
3. 查找
struct my_struct *find_user(int user_id) {
struct my_struct *s;
HASH_FIND_INT(users, &user_id, s);
return s;
}
4. 删除
void delete_user(struct my_struct *user) {
HASH_DEL(users, user);
free(user); //可选
}
注意事项
- 如果在Android/gcc编译时报
fall-through between switch labels
,则可以用pragma语句把uthash相关的代码括起来
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
// uthash相关代码
#pragma GCC diagnostic pop
其实还可以用__attribute__ ((fallthrough));
但是实测没有pragma这种方法好。
如果编译时报
padding struct 'struct UT_hash_table' with 4 bytes to align 'tail'
,可以按照https://github.com/troydhanson/uthash/issues/118#issue-223582662的回答,调整uthash.h中变量的顺序如果要当HashSet用,可能也需要额外声明一个变量,不然可能会出padding的问题,报
padding struct 'struct fd_struct' with 4 bytes to align 'hh'
,如下:
struct fd_struct {
int fd; // key
int padding; // 填充用,或者是char padding[10]之类的;
UT_hash_handle hh;
};