Find the max of a list using recursion
You have a portability bug, because names ending in _t are reserved for future Standard Library types.  Rename node_t, perhaps to Node.



This kind of recursion is problematic, because it can't be transformed into iterative form by the compiler.  It needs to keep each call's e value until all the inner recursive calls have completed, before it can do the comparison.

If you can, strive to make your function tail-recursive, which means that it's in the form:

ResultType function(args) {
    ...
    return function(other_args);
}


To make a non-tail recursive function into a tail-recursive one, you generally need to pass the current state into the recursive call.

Here, I'd actually split the function into two: a recursive function to find the node_t with largest value (or NULL if the list is empty), and a wrapper function to call it with the right parameters, extract the result, and handle errors:

/* untested */

static const Node *find_node_max(Node *list, Node *best_so_far)
{
    if (!list) {
       return best_so_far;
    }
    if (!best_so_far || list-&gt;val &gt; best_so_far-&gt;val) {
        best_so_far = list;
    }
    return find_node_max(list-&gt;next, best_so_far);
}

int trovaMassimo(const Node *head) {
    const Node *n = find_node_max(head, NULL);
    if (!n) {
        /* empty list - N.B. message to stderr, not stdout */
        fputs("Lista vuota\n", stderr);
        exit(1);   /* not good in library code */
    }
    return n-&gt;val;
}