openssl lhash 数据结构哈希表
哈希表是一种数据结构,通过在记录的存储位置和它的关键字之间建立确定的对应关系,来快速查询表中的数据;
openssl lhash.h 为我们提供了哈希表OPENSSL_LHASH 的相关接口,我们可以直接使用,用来存放各种数据;
哈希表类似前面提到的栈,但是哈希表的优势是查询速度快。
1. lhash.h 提供的哈希表主要接口有
//创建哈希表,参数为两个回调函数,分别可自定义哈希值计算方法,排序方法
OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c);
//释放哈希表内存,但是不释放表中数据的内存,需要调用下面的doall方法遍历表中数据去释放 void OPENSSL_LH_free(OPENSSL_LHASH *lh);
//在表中插入一条记录,当表中有该数据时,会进行替换,成功返回插入的数据地址 void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data);
//从表中删除一条记录,成功返回删除的该数据地址 void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data);
//从表中查询一条记录,参数为要查询数据的地址,成功返回表中该数据的地址 void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data);
//遍历表中的数据记录,回调函数可处理遍历每条记录 void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func);
//遍历表中的数据记录,多了一个arg参数,可看下面的测试 void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg);
//计算一条数据的哈希值 unsigned long OPENSSL_LH_strhash(const char *c);
//哈希表中元素个数 unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh);
//查看哈希表的状态,输出到FILE
void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp);
//查看哈希表节点的状态,输出到FILE void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp);
//查看哈希表节点的使用状态,输出到FILE void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp);
//以下接口为哈希表状态,输出到BIO void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out); void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out); void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
2. 测试代码
unsigned long hashff(void *hf) { printf("%s\n",hf); return 100; } int hashfCmp(int *a,int *b) { return *a > *b; } void printArg(int *a,char *b) { printf("doall_arg: %d %s\n",*a,b); } void printValue(int *value) { printf("doall: %d\n",*value); } int main(int argc, const char * argv[]) { OPENSSL_LHASH *lh = OPENSSL_LH_new(NULL, NULL); int item = 1; OPENSSL_LH_insert(lh, &item); int item2 = 10; OPENSSL_LH_insert(lh, &item2); int item3 = 5; OPENSSL_LH_insert(lh, &item3); //因为表中已经存在数据5,如果再插入,将会替换之前的数据5 int item4 = 5; int *ret=0; ret = OPENSSL_LH_insert(lh, &item4); if (*ret==item4) { printf("insert replace PASS\n"); } int *fd = 0; fd = OPENSSL_LH_retrieve(lh,&item2); if (*fd == item2) { printf("find value PASS\n"); } OPENSSL_LH_doall(lh, printValue); OPENSSL_LH_doall_arg(lh, printArg, "arg"); int *delRet = 0; delRet = OPENSSL_LH_delete(lh, &item4); if (*delRet==item4) { printf("delete value PASS\n"); } int numLen = OPENSSL_LH_num_items(lh); printf("len=%d\n"); OPENSSL_LH_stats(lh, stdout); OPENSSL_LH_free(lh); return 0; }
输出日志

insert replace PASS find value PASS doall: 10 doall: 1 doall: 5 doall_arg: 10 arg doall_arg: 1 arg doall_arg: 5 arg delete value PASS len=73832 num_items = 2 num_nodes = 8 num_alloc_nodes = 16 num_expands = 0 num_expand_reallocs = 0 num_contracts = 0 num_contract_reallocs = 0 num_hash_calls = 6 num_comp_calls = 3 num_insert = 3 num_replace = 1 num_delete = 1 num_no_delete = 0 num_retrieve = 1 num_retrieve_miss = 0 num_hash_comps = 6 Program ended with exit code: 0
测试使用 openssl 1.1.0c
参考:https://www.openssl.org/docs/man1.0.2/crypto/lhash.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2013-12-07 制作mac U盘启动