【问题标题】:Linked list in C – methodsC中的链表——方法
【发布时间】:2016-06-11 09:10:58
【问题描述】:

假设我们有节点的双向链表

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

typedef struct Node {
    int value;
    struct Node* next;
    struct Node* prev;
} Node;

typedef struct LinkedList {
    Node *first;
    Node *last;
} LinkedList;

void initList(LinkedList* l) {
    l->first = NULL;
    l->last = NULL;
}

我必须编写方法,该方法将具有给定值的新节点插入到列表的末尾并返回指向新节点的指针。我的尝试如下:

Node *insert(LinkedList *list, int value) {

    Node node;
    node.value = value;
    node.prev = list->last;
    node.next = NULL;

    if (list->last != NULL){
        (list->last)->next = &node;
    }else{
        list->first = &node;
        list->last = &node;
    }

    return &node;
}

看起来,在空列表中的插入是有效的,但它不适用于非空列表。

(有实现测试,它告诉我插入是否成功。我可以发布它们的代码,但不认为这很重要)。

请问,错误在哪里?

日志中有警告(第51行是'return &node')

C:\...\main.c|51|warning: function returns address of local variable [-Wreturn-local-addr]|

这是严重的问题吗?以及如何去除?


谢谢大家的解答,不过我觉得非空列表还是有问题的,因为根据测试,这个失败了:

void test_insert_nonempty(){
    printf("Test 2: ");

    LinkedList l;
    initList(&l);

    Node n;
    n.value = 1;
    n.next = NULL;
    l.first = &n;
    l.last = &n;

    insert(&l, 2);

    if (l.last == NULL) {
        printf("FAIL\n");
        return;
    }
    if ((l.last->value == 2) && (l.last->prev != NULL)) {
        printf("OK\n");
        free(l.last);
    }else{
        printf("FAIL\n");
    }
}

【问题讨论】:

    标签: c dynamic data-structures linked-list doubly-linked-list


    【解决方案1】:

    Node node; 是函数insert 中的局部变量。一旦您的函数终止并且不再定义,它就会被“销毁”。返回指向函数局部变量的指针是未定义的行为。您必须分配动态内存。动态分配内存被保留,直到你free它:

    Node *insert(LinkedList *list, int value) {
    
        Node *node = malloc( sizeof( Node ) ); // allocate dynamic memory for one node
        if ( node == NULL )
            return NULL; // faild to allocate dynamic memory
    
        node->value = value;
        node->prev = list->last;
        node->next = NULL;
    
        if ( list->first == NULL )
            list->first = node;      // new node is haed of list if list is empty
        else // if ( list->last != NULL ) // if list->first != NULL then list->last != NULL
            list->last->next = node; // successor of last node is new node
        list->last = node;           // tail of list is new node
    
        return node;
    }
    

    请注意,为避免内存泄漏,您必须在销毁列表时 free 列表的每个节点。

    【讨论】:

      【解决方案2】:

      您正在返回将在从函数返回时消失的非静态局部变量的地址,并且在从函数返回后取消引用该地址会调用 未定义的行为

      你必须分配一些缓冲区并返回它的地址。

      Node *insert(LinkedList *list, int value) {
      
          Node *node = malloc(sizeof(Node));
          if (node == NULL) return NULL;
          node->value = value;
          node->prev = list->last;
          node->next = NULL;
      
          if (list->last != NULL){
              (list->last)->next = node;
          }else{
              list->first = node;
              list->last = node;
          }
      
          return node;
      }
      

      【讨论】:

        【解决方案3】:

        你必须动态分配新节点。

        否则变量 node 在你的函数中

        Node *insert(LinkedList *list, int value) {
        
            Node node;
            //...
        

        是函数的局部变量,退出函数后将不再存活。因此,任何指向用于访问它的变量的指针都将无效。

        函数看起来像

        Node * insert( LinkedList *list, int value ) 
        {
            Node *node = malloc( sizeof( Node ) );
        
            if ( node != NULL )
            {
                node->value = value;
                node->prev = list->last;
                node->next = NULL;
        
                if ( list->last != NULL )
                {
                    list->last->next = node;
                }
                else
                {
                   list->first = node;
                }
        
                list->last = node;
            }
        
            return node;
        }
        

        【讨论】:

        • 我可以继续这个话题,回答与链接列表相关的其他问题,还是我需要创建一个新问题?
        • @byk7 你应该问一个新问题。
        猜你喜欢
        • 2012-09-20
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-27
        相关资源
        最近更新 更多