Search code examples
cpointerslinked-listsingly-linked-listpass-by-value

Having some doubts about C pointers and memory address


I'm really newbie in C and I have this piece of code about LinkedList in C:

struct ListNode* addnode(struct ListNode *head,int val)
{
    struct ListNode* newnode = malloc(sizeof(struct ListNode));
    newnode->val = val;
    newnode->next = NULL;
    if (!head) head = newnode;
    else {
        struct ListNode *this = head;
        while(this->next)
            this = this->next;
        this->next = newnode;
    }
    return head;
}

int main(void)
{
    struct ListNode *head = NULL;

    head = addnode(head,4);
    addnode(head,9);
    addnode(head,1);

    return 0;
}

My question is: in the main why if I write

    addnode(head,4);
    addnode(head,9);
    addnode(head,1);

Instead of

head = addnode(head,4);
    addnode(head,9);
    addnode(head,1);

Doesn't work ? The first one is creating the following linkedlist : 4->9->1, and the second one is creating 3 different Linkedlist heads. But wouldn't it be the same as we are always using the memory address of head ? So the head is always saving his previous node.

Thank you in advance I will appreciate your answers


Solution

  • Initially the pointer head is initialized as a null pointer

    struct ListNode *head = NULL;
    

    This pointer is passed by value to the function addnode

    addnode(head,4);
    

    The function deals with a copy of the value of the pointer head declared in main that is used as an argument expression of the function. Changing the copy does not influence on the original pointer head.

    So after the call the pointer head will still be a null pointer.

    The function returns the modified value of the copy of the pointer

    struct ListNode* addnode(struct ListNode *head,int val)
    {
        //... 
        if (!head) head = newnode;
        //...
        return head;
    }
    

    To change the original pointer head you need to assign the returned value to the pointer head like

    head = addnode(head,4);
    

    Now the pointer head points to the first node of the list.

    All other calls of the function

    addnode(head,9);
    addnode(head,1);
    

    append new nodes to the tail of the list. That is these calls do not influence on the value of the pointer that points to the first node of the list. So there is no need to assign the returned value of the function to the pointer head though nevertheless you could write

    head = addnode(head,9);
    head = addnode(head,1);
    

    To make it more clear consider a very simple example

    #include <stdio.h>
    
    int f( int x )
    {
        x += 1;
    
        return x;
    }
    
    int main( void )
    {
        x = 0;
    
        f( x );
    
        printf( "x = %d\n", x );
    }
    

    If you will not substitute this statement

        f( x );
    

    for

        x = f( x );
    

    then the variable x will not be changed in main after calling the function f because the function f changes a copy of the value of the variable x used as the function argument.