Official verbiage:
6.9.1 Function definitions
...
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.
where "undefined benavior" means:
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
C 2011 Online Draft
Believe it or not, a function typed something other than void
is not required to have a return
statement. It's not enforced by the language grammar, and there is no constraint that a non-void
function must contain a return
statement. The only constraints are that, if it is present, a return
statement in a void
function not return the value of any expression, and that a return
statement in a non-void
function must return the value of an expression.
Why is that the case?
C initially did not have a void
data type, and there was no way to specify a subroutine that was only executed for its side effects and didn't return a value. There was no good way to return "nothing", so the return
statement was not required. C also at this time had "implicit int
" declarations - you could define a function body without a type, and the compiler would assume it was typed int
:
foo( a, b ) // old style parameter declarations
int a; // still legal, but no longer really used
char *b; // for very good reasons
{
// do something interesting with a and b
}
foo
is implicitly typed to return int
, even if no value is explicitly being returned. This is okay as long as the caller doesn't try to use foo
's non-existent return value. So a convention sort of developed where "procedures" (functions executed solely for side effects) were not explicitly typed, and had no return
statement.
Because legacy code is forever, the behavior with respect to return
statements hasn't been changed in more recent versions of the C standard, even though implicit int
declarations were removed in C99.