Ever since I realized many years ago, that this doesn't produce an error by default (in GCC at least), I've always wondered why?
I understand that you can issue compiler flags to produce a warning, but shouldn't it always be an error? Why does it make sense for a non-void function not returning a value to be valid?
An example as requested in the comments:
#include <stdio.h>
int stringSize()
{
}
int main()
{
char cstring[5];
printf( "the last char is: %c\n", cstring[stringSize()-1] );
return 0;
}
...compiles.
I believe this is because of legacy code (C never required return statement so did C++). There is probably huge code base relying on that "feature". But at least there is
-Werror=return-type
flag on many compilers (including gcc and clang).C99 and C++ standards don't require functions to return a value. The missing return statement in a value-returning function will be defined (to return
0
) only in themain
function.The rationale includes that checking if every code path returns a value is quite difficult, and a return value could be set with embedded assembler or other tricky methods.
From C++11 draft:
§ 6.6.3/2
§ 3.6.1/5
Note that the behaviour described in C++ 6.6.3/2 is not the same in C.
gcc will give you a warning if you call it with -Wreturn-type option.
Just as a curiosity, look what this code does:
This code has formally undefined behaviour, and in practice it's calling convention and architecture dependent. On one particular system, with one particular compiler, the return value is the result of last expression evaluation, stored in the
eax
register of that system's processor.You mean, why flowing off the end of a value-returning function (i.e. exiting without an explicit
return
) is not an error?Firstly, in C whether a function returns something meaningful or not is only critical when the executing code actually uses the returned value. Maybe the language didn't want to force you to return anything when you know that you are not going to use it anyway most of the time.
Secondly, apparently the language specification did not want to force the compiler authors to detect and verify all possible control paths for the presence of an explicit
return
(although in many cases this is not that difficult to do). Also, some control paths might lead into to non-returning functions - the trait that is generally non known to the compiler. Such paths can become a source of annoying false positives.Note also, that C and C++ differ in their definitions of the behavior in this case. In C++ just flowing off the end of a value returning function is always undefined behavior (regardless of whether the function's result is used by the calling code). In C this causes undefined behavior only if the calling code tries to use the returned value.
Sounds like you need to turn up your compiler warnings:
Under what circumstances doesn't it produce an error? If it declares a return type and doesn't return something, it sounds like an error to me.
The one exception I can think of is the
main()
function, which doesn't need areturn
statement at all (at least in C++; I don't have either of the C standards handy). If there is no return, it will act as ifreturn 0;
is the last statement.It is a constraint violation in c99, but not in c89. Contrast:
c89:
c99:
Even in
--std=c99
mode, gcc will only throw a warning (although without needing to enable additional-W
flags, as is required by default or in c89/90).Edit to add that in c89, "reaching the
}
that terminates a function is equivalent to executing areturn
statement without an expression" (3.6.6.4). However, in c99 the behavior is undefined (6.9.1).