I have been programming using the C language for quite some time now. I recently came across a situation for which I need help. For a recursive call without a base condition, why does the compiler not show an error during compilation? I, however, receive an error message during runtime.
Take the following for an example. Thanks!
#include <iostream>
#include <climits>
int fibonacci(int n){
return fibonacci(n - 1) fibonacci(n - 2);
}
int main(){
int ans = fibonacci(6);
std::cout << ans << std::endl;
}
CodePudding user response:
The premise of the question is false. GCC reports:
: In function 'int fibonacci(int)': :6:5: warning: infinite recursion detected [-Winfinite-recursion] 6 | int fibonacci(int n){ | ^~~~~~~~~ :8:21: note: recursive call 8 | return fibonacci(n - 1) fibonacci(n - 2); | ~~~~~~~~~^~~~~~~
:6:21: warning: all paths through this function will call itself [-Winfinite-recursion] int fibonacci(int n){ ^ 1 warning generated.
(9) : warning C4717: 'fibonacci': recursive on all control paths, function will cause runtime stack overflow
CodePudding user response:
Modern compilers, in their quest to help you out and generate near-optimal code, will indeed recognize that this function never terminates. However, nothing in the C or C language specifications requires that. In contrast to languages like Prolog or Haskell, C/C do not guarantee any semantic analysis of your program. A very simple compiler would turn your code
int fibonacci(int n){
return fibonacci(n - 1) fibonacci(n - 2);
}
into a sequence of low-level instructions equivalent to
- set a = n - 1
- set b = n - 2
- put a in the stack position or register for the first int argument
- call function fibonacci
- move the return value into temporary x
- put b in the stack position or register for the first int argument
- call function fibonacci
- move the return value into temporary y
- set z = x y
- move z into the stack position or register for the function return value
- return to caller
This is a perfectly legal compilation of your program, and does not require any errors or warnings to be generated. Obviously, during execution, the "move the return value into temporary x" and later instructions (most significantly, the "return to caller") will never be reached. This will generate an infinite recursion loop until the machine stack space is exhausted.