简体   繁体   中英

Linked list in C – methods

Suppose we have doubly linked list of nodes

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

and I have to code method, which inserts a new node with given value to the end of the list and returns a pointer to the new node. My attempt follows:

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

It seems, that insertion in the empty list works, but it doesn't for a non-empty one.

(There are implementation tests, which tell me if an insertion was successful or not. I can post the codes of them, but don't think it's important).

So please, where are the mistakes?

There is a warning in the log (the 51st line is that with 'return &node')

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

Is that serious problem? And how to remove it?


Thank you for the answers, but I think there is still a problem with non-empty lists, because according to the test, this fails:

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

Node node; is a local variable in your function insert . It is "destroyed" as soon as your function terminates and is not longer defined. Returning a pointer to local variable of a function is undefined behavior. You have to allocate dynamic memory. Dynamically allocate memory is reserved until you free it:

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

Note to avoid memory leaks you have to free each node of the list, when you destroy the list.

You are returning address of non-static local variable which will vanish on returning from function, and dereferencing the address after returning from the function invokes undefined behavior .

You have to allocate some buffer and return its address.

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

You have to allocate the new node dynamically.

Otherwise variable node in your function

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

    Node node;
    //...

is a local variable of the function that will not be alive after exiting the function. As result any pointer to the variable used to access it will be invalid.

The function can look like

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM