Compile with a C99 or C11 compiler and read the warnings. You are using the function without prototype.
Without a prototype, pre-C99 assumes a function to return int
by default.
C99 and later, require a prototype.
Even without additional warnings enabled:
$ cat test.c
int main()
{
int i = f();
return 0;
}
int f(void)
{
return 1;
}
$ gcc -std=c11 test.c
test.c: In function ‘main’:
test.c:13:2: warning: implicit declaration of function ‘f’ [-Wimplicit-function-declaration]
int i = f();
Note that gcc will not warn if compiling -std=c90
, but will if enabling warnings -Wall
.
So, as higher()
is expected to return an int
, the value is converted to double
by the assignment (the type of c
is not changed).
And now for the funny part: undefined behaviour (UB, memorize this phrase!) due to different signature for call and implementation of the function.
What might happen is according to procedure call standard (PCS) and the application binary interface (ABI) - check Wikipedia. Briefly: higher
itself returns a double
. That is likely passed in a floating point CPU register to the caller. The caller, OTOH, expects the return value (due to the missing prototype) in an integer CPU register (which happens to hold 0
by chance).
So, as they apparently have misscommunication, you get the wrong result. Note that this is a bit speculatively and depends on the PCS/ABI. All to remember is this is UB, so anything can happen, even demons flying out of your nose.
Why use prototypes:
Well, you allready noticed, the compiler has no idea, if you call a function correctly. Even worse, it does not know, which argument types are used and which result type is returned. This is particlularily a problem, as C automatically converts some types (which you did encounter here).
As classical K&R (pre-standard) C did not have prototypes, all arguments to unknown functions were assumed int
/double
for scalar arguments on a call. The result defaults to int
. (Long time ago, I might be missing some parts; I started some coding with K&R, messed up types (exactly your problem here, but without a clean solution), etc., threw it in a corner and happily programmed in Modula-2 until some years later I tried ANSI-C).
If compiling code now, you should at least conform to (and compile for) C99, better use the current standard (C11).