Один из способов определить, происходит ли хвостовой вызов, состоит в том, чтобы проверить, можете ли вы вызвать переполнение стека. Следующая программа не производит переполнение стека при использовании VC ++ 2005 Express Edition, и, хотя ее результаты довольно быстро превосходят возможности long double, вы можете сказать, что все итерации обрабатываются, когда происходит TCO:
/* FibTail.c 0.00 UTF-8 dh:2008-11-23
* --|----1----|----2----|----3----|----4----|----5----|----6----|----*
*
* Demonstrate Fibonacci computation by tail call to see whether it is
* is eliminated through compiler optimization.
*/
#include <stdio.h>
long double fibcycle(long double f0, long double f1, unsigned i)
{ /* accumulate successive fib(n-i) values by tail calls */
if (i == 0) return f1;
return fibcycle(f1, f0+f1, --i);
}
long double fib(unsigned n)
{ /* the basic fib(n) setup and return. */
return fibcycle(1.0, 0.0, n);
}
int main(int argc, char* argv[ ])
{ /* compute some fibs until something breaks */
int i;
printf("\n i fib(i)\n\n");
for (i = 1; i > 0; i+=i)
{ /* Do for powers of 2 until i flips negative
or stack overflow, whichever comes first */
printf("%12d %30.20LG \n", i, fib((unsigned) i) );
}
printf("\n\n");
return 0;
}
Обратите внимание, однако, что упрощение создания чистого хвостового вызова в fibcycle равносильно выяснению интерактивной версии, которая вообще не выполняет хвостовой вызов (и будет работать с TCO или без в компиляторе.
Возможно, было бы интересно поэкспериментировать, чтобы увидеть, насколько хорошо TCO может найти оптимизации, которые еще не являются почти оптимальными и легко заменяются итерациями.