To benefit from tail-call optimization you have to reorganize the code. Here's one way to do it:
void bar(struct node *curr, struct node *prev, int pass)
{
if (pass == 1) printf("%d\n", curr->data);
if (pass > 1) return;
/* reverse current node */
struct node *next = curr->next;
curr->next = prev;
if (next) {
/* tail call with current pass */
bar(next, curr, pass);
} else {
/* end of list reached, go over list in reverse */
bar(curr, NULL, pass+1);
}
}
This function assumes that the end of the list is signaled by NULL
. The list is traversed in two passes: first to reverse it in-place, second to print the elements and reverse it again. And, as far as I can tell, gcc -O3
does a tail-call optimization so the algorithm runs in constant space.
To call this function use:
bar(&e1, NULL, 0);