Search code examples
clinked-listdouble-pointer

C double pointer meaning


I cannot understand the meaning of a C code about linked lists that is using double pointers. Here is the code I am reading

    struct list
{
    int value;
    struct list *next;
};
//Insert an element at the begining of the linked list
void insertBegin(struct list **L, int val)
{
    //What does **L mean?
    //Memory allocation for the new element temp
    struct list *temp;
    temp = (struct list *)malloc(sizeof(temp));
    //The new element temp points towards the begining of the linked list L
    temp->next = *L;
    //Set the beginning of the linked list
    *L = temp;
    (*L)->value = val;
}
void loop(struct list *L)
{
    printf("Loop\n");
    //Run through all elements of the list and print them
    while( L != NULL )
    {
        printf("%d\n", L->value);
        L = L->next;
    }
}
struct list* searchElement(struct list *L,int elem)
{
    while(L != NULL)
    {
        if(L->value == elem)
        {
            printf("Yes\n");
            return L->next;
        }
        L = L->next;
    }
    printf("No\n");
    return NULL;
}

int main()
{
    struct list *L = NULL;
    insertBegin(&L,10); // Why do I need 
    return 0;
}

What does **L in the insertElement mean and what is the difference between the **L and the *L in the loop function? Why in the main when struct list *L = NULL is declared I should call the function insertBegin with the argument &L and not a simple L?

I guess *L is a pointer towards the first node of the linked list while **L may point toward any element of the list. However, I am not sure this is correct.

Thank you for your help!


Solution

  • If you want a function to write to a parameter and have that new value reflected in the caller, then you must pass a pointer for that parameter:

    void foo( T *p ) // for any type T
    {
      *p = new_value(); // write a new value to the thing p points to
    }
    
    void bar( void )
    {
      T var;
      foo( &var ); // foo writes a new value to var
    }
    

    If we substitute T with a pointer type Q *, then the code is

    void foo( Q **p ) // for any type Q
    {
      *p = new_value(); // write a new value to what p points to
    }
    
    void bar( void )
    {
      Q *var;
      foo( &var ); // foo writes a new value to var
    }
    

    The semantics in both cases are exactly the same; we want foo to update the value stored in var through the pointer p. The only difference is that in the second case var already has a pointer type, so p has to be a pointer to that pointer type.

    In the code you posted, the insertBegin function updates the value stored in L, which is a pointer to the head of the list. Since the variable L in main has type struct list *, the type of the parameter L in insertBegin needs to be struct list **.