使用klib的khash库:KHASH_SET_INIT_INT64能否支持负数键?
问题与解答
代码示例
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include "klib/khash.h" KHASH_SET_INIT_INT64(bin_value); int counter = 1; int main() { khash_t(bin_value) *bin_value_pointer = kh_init(bin_value); FILE *file = fopen("read.txt", "r"); char line[20]; while (fgets(line, sizeof(line), file)) { int64_t value; int ret; if (sscanf(line, "%ld", &value) == 1) { kh_put(bin_value, bin_value_pointer, value, &ret); } } fclose(file); FILE *file1 = fopen("check.txt", "r"); while (fgets(line, sizeof(line), file1)) { int64_t input; int ret; if (sscanf(line, "%ld", &input) == 1) { if (kh_get(bin_value, bin_value_pointer, input) != kh_end(bin_value_pointer)) { printf("matched counter= %d\n", counter++); } } } kh_destroy(bin_value, bin_value_pointer); fclose(file1); return 0; }
用户提问
我正在尝试用khash实现哈希集合(hashSet),发现头文件中KHASH_SET_INIT_INT64使用的是unsigned long int(uint64_t),请问是否可以将负数作为键?使用负数键是否会引发问题?我是C语言新手,抱歉提出这类问题。
解答
1. 能否用负数作为键?
语法上可以编译通过,但本质是C语言的隐式类型转换在起作用:当你把int64_t类型的负数传入为uint64_t设计的哈希集合时,负数会被转换成对应的无符号64位整数(比如-1会变成0xFFFFFFFFFFFFFFFF)。
由于补码系统中int64_t和uint64_t的内存表示是一一对应的,每个负数都会对应唯一的无符号值,不会和正数的键冲突,所以实际运行时可以正常存储和匹配负数键。
2. 可能引发的问题
- 语义混淆:哈希表实际存储的是无符号值,调试时如果查看哈希表内部数据,会看到负数对应的无符号形式,容易造成理解上的混乱。
- 逻辑风险:如果后续代码中不小心将
uint64_t类型的正数与int64_t负数混用,可能出现意外的匹配(比如某个正数刚好等于负数转换后的无符号值),不过这种情况只要业务逻辑清晰就可以避免。
3. 更合适的解决方案
如果你明确需要存储int64_t类型(包含负数),建议直接使用针对有符号64位整数的哈希集合定义,避免类型转换的问题:
将原代码中的KHASH_SET_INIT_INT64(bin_value);替换为:
KHASH_SET_INIT2(bin_value, int64_t, kh_int64_hash, kh_int64_equal);
这个宏直接指定键类型为int64_t,并使用对应的哈希函数和比较函数,负数处理完全符合预期,不需要担心类型转换带来的问题。
内容的提问来源于stack exchange,提问作者Frozen_Blood
相关产品推荐
相关产品推荐

