实现链表时指针奇怪的问题

我正在尝试在C中实现链接列表,并且我想将头节点存储在单独的结构中。 但是,每当我添加另一个节点时,似乎都会以某种方式重新分配头节点。

#include  #include  struct BC_node { struct BC_node *next; void *data; }; struct BC_list { struct BC_node *head; struct BC_node *tail; }; void BC_list_push(struct BC_list *list, void *data) { struct BC_node *node = calloc(1, sizeof(struct BC_node)); if (list->head != NULL) printf("head: %d\n", *((int *) (list->head)->data)); node->next = NULL; node->data = data; if (list->head == NULL) { printf("head is null.\n"); list->head = node; } if (list->tail != NULL) { (list->tail)->next = node; } list->tail = node; printf("head: %d\n", *((int *) (list->head)->data)); } int main(void) { int i; struct BC_list *list = calloc(1, sizeof(struct BC_list)); list->head = NULL; list->tail = NULL; for (i = 0; i < 3; i++) BC_list_push(list, &i); return 0; } 

输出:

 head is null. head: 0 head: 1 head: 1 head: 2 head: 2 

您的data成员只是指向main变量i的指针,因此当您打印*data您只需在循环的那一轮中看到计数器的值。 您的所有节点都具有相同的数据值!

问题是这一行:

 BC_list_push(list, &i); 

您正在传递i的地址,这是您在循环中递增的整数(因此值会更改)。 您需要为data参数分配单独的内存。

 for (i = 0; i < 3; i++) { int *d = malloc(sizeof(int)); *d = i; BC_list_push(list, d); } 

但是当列表被销毁时不要忘记释放内存。

情况更糟。 &i是局部变量的地址,这意味着你从堆分配列表引用堆栈,volatile变量……这是完全错误的 – 如果你在一个不同于main的方法中执行它,那么你有一个局部变量将消失,你的指针将指向内存中的一些随机位置,可能指向其他变量或地址……非常糟糕。

这是一个完整的示例,包含数据的结构和内存分配,

 #include  #include  #include  struct BC_node{ void *data; struct BC_node *next; }; struct BC_list{ struct BC_node *head; struct BC_node *tail; }; struct BC_node *BC_new_node(void *data,size_t szdata) { struct BC_node *ptr=malloc(sizeof(struct BC_node)); if(ptr!=NULL){ ptr->data=malloc(szdata); ptr->next=NULL; if(ptr->data!=NULL) memcpy(ptr->data,data,szdata); else free(ptr),ptr=NULL; } return ptr; } int BC_list_push(struct BC_list *list,void *data,size_t szdata) { struct BC_node *ptr=BC_new_node(data,szdata); if(list!=NULL && ptr!=NULL){ if(list->tail==NULL){ list->head=ptr; list->tail=ptr; } else { list->tail->next=ptr; list->tail=ptr; } return 0; } return 1; } void *BC_new_list(void) { struct BC_list *ptr=malloc(sizeof(struct BC_list)); if(ptr!=NULL) ptr->head=ptr->tail=NULL; return ptr; } void BC_free_list(struct BC_list *list) { struct BC_node *ptr; while(list->head){ ptr=list->head->next; free(list->head->data); free(list->head); list->head=ptr; } free(list); } void print_test(struct BC_list *list){ struct BC_node *ptr=list->head; while(ptr){ printf("%s\n",(char*)ptr->data); ptr=ptr->next; } } int main(void) { char tab[3][40]={"hello","world","test"}; struct BC_list *list=BC_new_list(); if(list!=NULL){ BC_list_push(list,tab[0],strlen(tab[0])+1); BC_list_push(list,tab[1],strlen(tab[1])+1); BC_list_push(list,tab[2],strlen(tab[2])+1); print_test(list); BC_free_list(list); } return EXIT_SUCCESS; }