Removing nodes from a linked list
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;
}