【问题标题】:Odd problem with pointer while implementing a linked list实现链表时指针的奇怪问题
【发布时间】:2023-04-07 11:35:01
【问题描述】:

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

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

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

【问题讨论】:

    标签: c pointers struct linked-list


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      问题出在这一行:

      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);
      }
      

      但不要忘记在列表销毁时释放内存。

      【讨论】:

        【解决方案3】:

        情况更糟。 &i 是局部变量的地址,这意味着您从堆分配的列表中引用堆栈,易失性变量...这完全是错误的-如果您使用不同于 main 的方法执行此操作,那么您拥有的局部变量将消失,您的指针将指向内存中的某个随机位置,可能指向其他变量或地址......非常糟糕。

        【讨论】:

          【解决方案4】:

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

          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          
          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;
            }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-07-17
            • 2020-01-22
            • 2011-03-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-28
            • 1970-01-01
            相关资源
            最近更新 更多