I have successfully compiled and executed the following code in GCC:
#include <stdio.h>
int foo()
{
}
int main()
{
int i = 12345;
i = foo();
printf("i is: %d", i);
}
The output is:
i is: 0
So GCC allowed me not to return from the function foo()
and made foo()
return 0
.
Does this behavior only apply to GCC or do other C standards also have it (based on my understanding, GCC does not conform to any C standard)?
The C standard does not say a function must return a value or that, if it does not, the behavior is undefined. If the value is used by the caller, then the behavior is undefined, because C 2018 6.9.
A function that returns void means it does not return a value at all. C does not allow you to use the return statement with an expression (even if it is a void one) if your function is declared as void .
It means that that function does not return a value to the caller explicitly.
Void functions are created and used just like value-returning functions except they do not return a value after the function executes. In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value.
None of the C standards require the compiler to produce an error or warning if a function is missing a return statement¹.
In all of the C standards the behaviour is undefined if control flow reaches the end of non-void function without a return
and the return value of the function is then used (as in your code).
So if by "allow" you mean "specify it as legal, well-defined behaviour", none of the C standards allow your code. If you just mean "don't require an implementation to produce an error", all of them do.
Do note that the value of i
in your example program can easily change if you change the definition of foo
(without adding a return
). You can not rely on it being 0. There is no rule that says "if there's no return, return 0" - neither in the standard nor in GCC's implementation. According to the standard it's undefined and in GCC it will just be whatever happens to be in the return register at that time.
¹ In the general case this would be undecidable. One could do what e.g. Java does and define the rules so that some otherwise valid function definitions are rejected, but none of the C standards do this.
gcc does give a warning:
warning: control reaches end of non-void function [-Wreturn-type]|
(Disclaimer: I get different results from different versions of gcc. To be sure, compile with -Wall -Wextra -pedantic-errors
.)
What happens in this case is not covered by the C standard. The standard merely says that (C11 6.9.1/12):
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
In your case, the caller does use the return value by storing it in i
. So this is undefined behavior - the behavior is not covered by the C standard and the compiler has no obligation to inform you about it. Anything could happen. So this should be regarded as a bug in most cases.
Well, there is nothing in the standard that stops you from writing illegal code. However, it does mention that this is undefined behaviour.
Quoting C11, chapter §6.9.1:
If the
}
that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
C89 states (at least in the draft):
If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined.
Which means it's legal to write code as you did. It's not an error. It's undefined behavior, but it's syntactically legal. Since it's not specifically "illegal" and syntactically allowed a compiler adhering to C89 may very well just compile it and the result will be undefined... but it's a legit program as far as the compiler is concerned.
That's why even with -Wpedantic it's probably not going to be rejected. Undefined behaviour means exactly what it says: it's undefined what happens. Be aware that compilers may optimize undefined behaviour away completely (which is ok, because it's undefined behaviour anyway, so the compiler can do whatever it wants).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With