Search code examples
cstructlinked-listsingly-linked-listfunction-definition

Incompatible types error from pointer to pointer


void remove_element(struct Node *list)
{   
    struct Node *temp = list;
    printf("Enter the element value you want to remove");
    int value;
    scanf("%d",&value);
    if(temp->data == value){ //first node is to be deleted
        *list = temp->next; // error here
        free(temp);
    }
}

Error :incompatible types when assigning to type 'struct Node' from type 'struct Node *'| Though this has been successfully compiled

 struct Node *temp = list; 

This line is similar but shows no error.


Solution

  • As the parameter list is declared like

    struct Node *list
    

    then the expression *list used in this statement

    *list = temp->next;
    

    has the type struct Node while the right side hand operand has the type struct Node *.

    You have to write

    list = temp->next;
    

    But in any case pay attention to that the function can invoke undefined behavior when the passed list is empty. And it should search a node for the target value instead of checking only the head node whether it contains the target value.

    And the worst is the function even does not change the pointer to the head node because the pointer is passed to the function by value. So this statement

        list = temp->next; // error here
    

    changes a copy of the original pointer to the head node not the original pointer itself declared in main.

    The function should be defined at least like

    int remove_element( struct Node **list )
    {   
        printf( "Enter the element value you want to remove: " );
        int value;
        
        int success = scanf( "%d", &value ) == 1;
    
        if ( success )
        {
            while ( *list != NULL && ( *list )->data != value )
            {
                list = &( *list )->next;
            }
    
            success = *list != NULL;
    
            if ( success )
            {
                struct Node *tmp = *list;
                *list = ( *list )->next;
                free( tmp );
            }
        }
    
        return success;
    }
    

    If in main you have a declaration

    struct Node *list = NULL;
    //...
    

    then the function must be called like

    remove_element( &list );
    

    or something like

    if ( remove_element( &list ) )
    {
        puts( "A node was removed." );
    }
    

    Also it would be better if the function would do only one thing: deleting a node. The prompt for a value that must be deleted should be placed outside the function. In this case the function can be defined the following way

    int remove_element( struct Node **list, int value )
    {   
        while ( *list != NULL && ( *list )->data != value )
        {
            list = &( *list )->next;
        }
    
        int success = *list != NULL;
    
        if ( success )
        {
            struct Node *tmp = *list;
            *list = ( *list )->next;
            free( tmp );
        }
    
        return success;
    }
    

    Here is a demonstrative program.

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Node
    {
        int data;
        struct Node *next;
    };
        
        
    int push_front( struct Node **list, int data )
    {
        struct Node *temp = malloc( sizeof( struct Node ) );
        int success = temp != NULL;
    
        if ( success )
        {       
            temp->data = data;
            temp->next  = *list;
            *list = temp;
            
        }
    
        return success;
    }
    
    void clear( struct Node **list )
    {
        while ( *list != NULL )
        {
            struct Node *temp = *list;
            *list = ( *list )->next;
            free( temp );
        }
    }
    
    void display( const struct Node *list )
    {
        for ( const struct Node *current = list; current != NULL; current = current->next ) 
        {
            printf( "%d -> ", current->data );
        }
        
        puts( "null" );
    }
    
    int remove_element( struct Node **list, int value )
    {   
        while ( *list != NULL && ( *list )->data != value )
        {
            list = &( *list )->next;
        }
    
        int success = *list != NULL;
    
        if ( success )
        {
            struct Node *tmp = *list;
            *list = ( *list )->next;
            free( tmp );
        }
    
        return success;
    }
    
    int main(void) 
    {
        struct Node *list = NULL;
        
        const int N = 10;
        
        for ( int i = N; i != 0; i-- )
        {
            push_front( &list, i );
        }
        
        display( list );
        
        int value = 1;
        
        if ( remove_element( &list, value ) )
        {
            printf( "The element with the value %d was removed.\n", value );
            
        }
    
        display( list );
    
        value = 10;
        
        if ( remove_element( &list, value ) )
        {
            printf( "The element with the value %d was removed.\n", value );
            
        }
    
        display( list );
    
        value = 5;
        
        if ( remove_element( &list, value ) )
        {
            printf( "The element with the value %d was removed.\n", value );
            
        }
    
        display( list );
    
        clear( &list );
        
        display( list );
    
        return 0;
    }
    

    Its output is

    1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
    The element with the value 1 was removed.
    2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
    The element with the value 10 was removed.
    2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
    The element with the value 5 was removed.
    2 -> 3 -> 4 -> 6 -> 7 -> 8 -> 9 -> null
    null