Edit: I notice you have rewritten your question as I wrote this. I believe it still answers your question though:
Let's forget about Scheme and other languages for a moment.Why? You only have to turn optimization on to end up with code using far less resources than Scheme can ever dream of.
With the same numeric result of course, except that the optimized C version wont eventually crash.
Let's read what the C standard says. For example : INTERNATIONAL STANDARD ©ISO/IEC ISO/IEC 9899:2017 Programming languages — C here: http://www.open-std.org/jtc1/sc22/wg14/ ... /n2310.pdf
Talk of recursion in there is sparse but it starts out well:
But here is the killer for using tail calls in C:126.96.36.199 Function calls
11 Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions.
Right there it says, twice in the same section, that new object instances are created every time the scope that they are declared in is entered.6.2.4 Storage Duration of Objects
6 ... If the block is entered recursively, a new instance of the object is created each time...
7. For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.35) If the scope is entered recursively, a new instance of the object is created each time.
I take that to mean function parameters, and local variables etc.
It basically spells it out that a recursive function will eat resources and an infinite recursion, or just deep recursion, will eventually consume all available space with new object instances and your program will crash.
Ergo, it's as well to assume C does not guarantee tail call optimization.
Personally I find it bizarre to argue that creating code that only works properly with optimization turned on, provided you have the right compiler, provided it actually decides to use tail call optimization in your case, provided the moon is in the correct phase, is a good idea.
If nothing else it's not standards compliant, it's behavior is UB, it makes the code less portable, it makes it hard to run under a debugger.
Having said all that, it's great that GCC/LLVM and such optimize tail calls, if only for the performance benefits. If the issues with it I mention don't bother you then by all means abuse it.