C 简单哈希表中的Segfault

C 简单哈希表中的Segfault,c,segmentation-fault,hashtable,C,Segmentation Fault,Hashtable,我正试图用C编写一个简单的哈希表,但在使用mymain()所示的代码进行测试时,我遇到了一个非常奇怪的错误 设计:我有一个哈希表,其底层数组大小为10000。我持有一个指向结构节点(或节点)指针数组开头的双指针。当我想put()将某些内容放入哈希表时,我会检查相应位置的节点元素是否为NULL。如果是,我将创建一个新节点来填充该点,否则,如果存在碰撞,我将从碰撞节点构建一个链接列表 场景:在main()中,我试图将编号3328放入哈希表中。相反,程序会自动排除故障。这对我来说毫无意义,因为前面的p

我正试图用C编写一个简单的哈希表,但在使用my
main()
所示的代码进行测试时,我遇到了一个非常奇怪的错误

设计:我有一个哈希表,其底层数组大小为10000。我持有一个指向
结构节点
(或
节点
)指针数组开头的双指针。当我想
put()
将某些内容放入哈希表时,我会检查相应位置的
节点
元素是否为
NULL
。如果是,我将创建一个新节点来填充该点,否则,如果存在碰撞,我将从碰撞节点构建一个链接列表

场景:
main()
中,我试图
将编号3328放入哈希表中。相反,程序会自动排除故障。这对我来说毫无意义,因为前面的
put()
工作正常,您可以清楚地看到我将所有初始指针设置为NULL。据我所知,引用哈希表位置3328的指针没有被设置为NULL,因为当我在
put()
函数中取消引用它时,它会出错。我的主函数看起来应该将所有指针都设置为NULL,尽管

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int TABLE_SIZE = 10000;

typedef struct node_t {
    int key;
    int value;
    struct node_t* next;
} node;

node** table;

inline node** get_node_address(int key) {
    key = (key > -key ? key : -key) % TABLE_SIZE;
    return (node**) (table + key * sizeof(node*)); 
}

inline node* new_node(int key, int value) {
    node* n = malloc(sizeof(node));
    n->key = key;
    n->value = value;
    n->next = NULL;
    return n;
}

void put(int key, int value) {
    node** n = (node**) get_node_address(key);
    node* iterator = (node*) *n;

    if (*n == NULL) {
        *n = new_node(key, value);
    } else {
        while (iterator->next != NULL)
            iterator = iterator->next;

        iterator->next = new_node(key, value);
    }
}

int* get(int key) {
    node* iterator = (node*) *get_node_address(key);

    while (iterator != NULL && iterator->key != key) {
        iterator = iterator->next;
    }

    if (iterator == NULL)
        return NULL;
    else
        return &(iterator->value); 
}

int main() {
    printf("Starting..\n");

    int i;
    table = malloc(sizeof(node*) * TABLE_SIZE);
    memset(table, 0, sizeof(node*) * TABLE_SIZE);

    for (i = 0; i < TABLE_SIZE; i++) {
        table[i] = NULL;
        printf("setting %x\n", &table[i]);
    }

    printf("before bad: %x\n", *get_node_address(3327));
    printf("bad address: %x\n", *get_node_address(3328));
    printf("last address: %x\n", table + sizeof(node*) * TABLE_SIZE);

    printf("Hashing...\n");

    put(3328, 3338);
    printf("%d", *get(3328));

    return 0;
}
#包括
#包括
#包括
int TABLE_SIZE=10000;
类型定义结构节点{
int键;
int值;
结构节点*next;
}节点;
节点**表;
内联节点**获取节点地址(int键){
key=(key>-key?key:-key)%TABLE\u大小;
返回(节点**)(表+键*sizeof(节点*);
}
内联节点*新节点(int键,int值){
node*n=malloc(sizeof(node));
n->key=key;
n->value=value;
n->next=NULL;
返回n;
}
无效放置(int键,int值){
节点**n=(节点**)获取节点地址(键);
节点*迭代器=(节点*)*n;
如果(*n==NULL){
*n=新的_节点(键、值);
}否则{
while(迭代器->下一步!=NULL)
迭代器=迭代器->下一步;
迭代器->下一步=新节点(键,值);
}
}
int*get(int键){
节点*迭代器=(节点*)*获取节点\地址(键);
while(迭代器!=NULL&&iterator->key!=key){
迭代器=迭代器->下一步;
}
if(迭代器==NULL)
返回NULL;
其他的
返回&(迭代器->值);
}
int main(){
printf(“开始…\n”);
int i;
table=malloc(sizeof(node*)*表大小);
memset(表,0,sizeof(节点*)*表大小);
对于(i=0;i
至少有一个问题:

inline node** get_node_address(int key) {
      key = (key > -key ? key : -key) % TABLE_SIZE;
      return (node**) (table + key * sizeof(node*)); /* <---- */
}
内联节点**获取节点地址(int键){
key=(key>-key?key:-key)%TABLE\u大小;

return(node**)(table+key*sizeof(node*);/*至少有一个问题:

inline node** get_node_address(int key) {
      key = (key > -key ? key : -key) % TABLE_SIZE;
      return (node**) (table + key * sizeof(node*)); /* <---- */
}
内联节点**获取节点地址(int键){
key=(key>-key?key:-key)%TABLE\u大小;

return(node**)(table+key*sizeof(node*);/*上述代码可以简化很多:

void put(int key, int value) {
  node **n = get_node_address(key);


  for (n = get_node_address(key); *n; n = &(*n)->next) {;}

  if(*n == NULL)
    *n = new_node(key, value);

}

int* get(int key) {
  node  **n;

  for (n = get_node_address(key); *n; n = &(*n)->next) {
    if (n->key == key) break;
    }

  if(*n == NULL)
    return NULL;
  else
    return &(*n)->value; 
}

上述代码可以简化很多:

void put(int key, int value) {
  node **n = get_node_address(key);


  for (n = get_node_address(key); *n; n = &(*n)->next) {;}

  if(*n == NULL)
    *n = new_node(key, value);

}

int* get(int key) {
  node  **n;

  for (n = get_node_address(key); *n; n = &(*n)->next) {
    if (n->key == key) break;
    }

  if(*n == NULL)
    return NULL;
  else
    return &(*n)->value; 
}

你试过用调试器来调试你的程序吗?
key>=0有什么问题吗?key:-key
???你试过用调试器来调试你的程序吗?key:-key>=0有什么问题吗?key:-key
???哇,我从来没想过。我改变了它,它工作得很完美!所以在指针算法中,如果其中一个值不正确指针本身,C会乘以指针的大小吗?@Daniel在指针算术中,它会乘以指针类型的大小。语法
return&table[key];
不太容易出错,而且可能更具可读性。哇,我从来没有想到过。我改变了它,它工作得完美无缺!所以在指针算法中,如果其中一个值本身不是指针,C将乘以我的指针大小?@Daniel在指针算法中,它将乘以指针类型的大小。语法
return&table[key];
不太容易出错,而且可能更具可读性。