Removing nodes from a linked list This is my second iteration of a function to remove all nodes containing value 'x'.  The previous iteration is here.

This function takes as input the head of a list and has to delete all the nodes that contain a given value taken.  Is this an improvement on the previous iteration?  Is there anything else that can be improved?

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



node_t *rimuovi(node_t *head, int x){

    node_t *temp = head;
    node_t *curr = head;

    if (head == NULL){
        printf("Lista vuota, finito!\n");
        return head;
    }

    while(head-&gt;val == x){
        if (head-&gt;next == NULL){
            free(head);
            printf("La lista adesso e' vuota. Finito\n");
            return head;
        }
        else {
            curr = head-&gt;next;
            free(head);
            head = curr;
        }
    }

    temp = head;
    curr = temp-&gt;next;

    while (curr != NULL){
        if (curr-&gt;val == x){
            if(curr-&gt;next != NULL){
                temp-&gt;next = curr-&gt;next;
                free (curr);
                curr = temp-&gt;next; 
            }
            else {
                temp-&gt;next = NULL;
            }
        }
        else {
            temp = curr;
            curr = curr-&gt;next;
        }
    }

    return head;
}
Bug: Returning a free'd pointer!

After freeing a pointer, do not use it.

        free(head);
        printf("La lista adesso e' vuota. Finito\n");
        // return head;
        return NULL;





  Is there anything else that can be improved?


Rather than 2 or 3 cases to handle an empty list, list of only matches or mixed list, consider a code simplification.

Create a temporary pre-head node and assign its next to the head.  Only 1 case  needed.  This approach is reasonable when node_t is not large.

Some untested code.

node_t *rimuovi(node_t *head, int x) {
  node_t pre_head;
  node_t *p = &amp;pre_head;
  pre_head.next = head;  // Other members are not used.

  while (p-&gt;next) {
    if (p-&gt;next-&gt;val == x) {
      node_t *next = p-&gt;next-&gt;next;
      free(p-&gt;next);
      p-&gt;next = next;
    } else {
      p = p-&gt;next;
    }
  }
  return pre_head.next;
}