【发布时间】:2018-11-08 23:02:11
【问题描述】:
您好,我正在尝试在常规 C 中实现一个非常简单的哈希映射,其中一个字符串作为键,一个 void 指针作为值,因为我希望将映射用于多种数据类型。
到目前为止我有这个
struct node{
void * value;
char * key;
};
unsigned long strhash(char *string)
{
unsigned long hash = 5381;
int c;
while ((c = *string++))
{
hash = ((hash << 5) + hash) + c;
}
return hash;
}
map_t *map_create(int maxSize){
map_t *map = malloc(sizeof(map_t));
map->curSize = 0;
map->maxSize = maxSize;
map->nodes = calloc(map->maxSize, sizeof(node_t *));
return map;
}
node_t *node_create(char *key, void *value){
node_t *node = malloc(sizeof(node_t));
node->key = key;
node->value = value;
return node;
}
void map_insert(map_t *map, char *key, void *value){
node_t *node = node_create(key, value);
int idx = strhash(key) % map->maxSize;
if(map->nodes[idx] == NULL){
map->nodes[idx] = node;
}else{
while(map->nodes[idx] != NULL){
idx++%map->maxSize;
}
map->nodes[idx] = node;
}
return;
}
void map_print(map_t *map){
for(int i = 0; i < map->maxSize; i++){
if(map->nodes[i] != NULL){
printf("index: %d\t value: %d\n",i, *(int*)map->nodes[i]->value);
}
}
return;
}
void map_destroy(map_t *map){
for(int i = 0; i < map->maxSize; i++){
if(map->nodes[i] != NULL){
free(map->nodes[i]);
}
}
free(map->nodes);
free(map);
return;
}
int main(){
map_t *map = map_create(32);
for(int i = 0; i < 30; i++){
map_insert(map, (char*)&i, &i);
}
map_print(map);
map_destroy(map);
return 0;
}
问题是当地图被打印时,输出并不像我所期望的那样,所有检索到的是所有索引上的值“30”,这是插入到地图中的最后一个数字。如果我将值更改为 int 类型,则映射按预期工作,那么在指针方面我必须缺少一些关键的东西。
我在 C 方面不是最优秀的,所以任何可以阐明这一点的观点都将不胜感激。
【问题讨论】:
-
您每次都在存储
i变量的地址。该地址不会改变,但每次分配给它时都会改变内容。 -
^ 这解释了为什么更改为
int value有效,因为 i 的值被复制了 -
更糟的是,一旦到达
map_print,i就不再在作用域内,因此这些条目中的每一个现在都承载了一个悬空指针。取消引用它会调用 未定义的行为。 -
仅供参考,如果您正在寻找有用的东西,您可以在这里找到一个不错的免费方法:github.com/rxi/map
标签: c pointers hashmap void-pointers