Search code examples
cstructlinked-liststackfunction-definition

Can someone please explain the function pop (more especifically the variable retval) of the following code?


I'm having some trouble understanding structures and would be very grateful if any of you could explain the function pop and what is retval in this context. Thank you in advance! The code is presented here:

 typedef struct node {
     int val;
     struct node * next;
} node_t;

int pop(node_t ** head) {
    int retval = -1;
    node_t * next_node = NULL;

    if (*head == NULL) {
        return -1;
    }

    next_node = (*head)->next;
    retval = (*head)->val;
    free(*head);
    *head = next_node;

    return retval;
}

Solution

  • It is a bad function definition. For example its return value can confuse users of the function: whether the returned value -1 is an actual value stored in the stack or it is an error code.

    There are used initializers of variables values of which are not used anywhere else within the function like for example

    int retval = -1;
    

    or

    node_t * next_node = NULL;
    

    The function can be defined the following way

    int pop( node_t **head, int *value ) 
    {
        int success = *head != NULL;
    
        if (success )
        {
            *value = ( *head )->val;
    
            node_t *tmp = *head;
    
            *head = ( *head )->next;
    
            free( tmp );
        }
    
        return success;
    }
    

    And the function can be called like

    node_t *head = NULL;
    //...
    
    int value;
    
    if ( pop( &head, &value ) )
    {
        printf( "The value stored on the top of the stack is %d\n", value );
    }
    

    Also it is convenient to use such a function in a loop. For example

    int value;
    while ( pop( &head, &value ) )
    {
        printf( "%d ", value );
    }
    puts( "-> the stack is empty." );
    

    What is the function doing?

    The function pops a value that is stored on the stack. If the stack is empty

        int success = *head != NULL;
    

    that is when *head is equal to NULL the function returns 0 - the value of the expression *head != NULL in this case this means for the user of the function that the stack was empty and there is nothing to pop.

    Otherwise the value stored on the stack is copied in the parameter value and the node that kept the value is removed from the list and its memory is freed. And the function returns the value of the variable success that in this case is equal to 1.

        if (success )
        {
            value = ( *head )->val;
    
            node_t *tmp = *head;
    
            *head = ( *head )->next;
    
            free( tmp );
        }
    
        return success;
    

    Here is a demonstration program.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node 
    {
        int val;
        struct node *next;
    } node_t;
    
    int push( node_t **head, int value )
    {
        node_t *new_node = malloc( sizeof ( node_t ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->val  = value;
            new_node->next = *head;
            *head = new_node;
        }
    
        return success;
    }
    
    int pop( node_t **head, int *value ) 
    {
        int success = *head != NULL;
    
        if (success )
        {
            *value = ( *head )->val;
    
            node_t *tmp = *head;
    
            *head = ( *head )->next;
    
            free( tmp );
        }
    
        return success;
    }
    
    int main(void) 
    {
        node_t *head = NULL;
    
        const int N = 10;
    
        int i = N;
    
        while ( i != 0 && push( &head, i  ) ) --i;
    
        int value;
    
        printf( "The stack contained: " );
    
        while ( pop( &head, &value ) )
        {
            printf( "%d ", value );
        }
        putchar( '\n' );
    
        return 0;
    }
    

    The program output is

    The stack contained: 1 2 3 4 5 6 7 8 9 10