Why isn't there any compiler error when a return statement is not present?
Unlike Java, in C/C++ the following is allowed:
int* foo ()
{
if(x)
return p;
// What if control reaches here?
}
This often causes cr开发者_开发知识库ashes and it is hard to debug problems. Why doesn't the standard enforce to have a final return for non-void
functions? (Compilers generate an error for a wrong return
value.)
Is there a flag in GCC or MSVC to enforce this? (something like -Wunused-result
)
It is not allowed (undefined behaviour). However, the standard does not require a diagnostic in this case.
The standard doesn't require the last statement to be return
because of code like this:
while (true) {
if (condition) return 0;
}
This always returns 0, but a dumb compiler cannot see it. Note that the standard does not mandate smart compilers. A return
statement after the while
block would be a waste which a dumb compiler would not be able to optimise out. The standard does not want to require the programmer to write waste code just to satisfy a dumb compiler.
g++ -Wall is smart enough to emit a diagnostic on my machine.
Use the -Wall flag in GCC.
warning: control reaches end of non-void function
Or more specifically, -Wreturn-type.
My guess: Because sometimes the programmer knows better than the compiler. With this simple example, it's clear that someting is wrong, but consider a switch of many values, or many checks in general. You, as the coder, know that certain values just will not be passed in to the function, but the compiler doesn't and just hints you, that there might be something wrong.
#include <iostream>
int foo(){
if(false)
return 5;
}
int main(){
int i = foo();
std::cout << i;
}
Note that even warning level 1 on MSVC gives the following warning:
warning C4715: 'foo' : not all control paths return a value
You can convert the warning into an error by using the following compiler options
-Wreturn-type -Werror=return-type
.
Check out This link
The obvious answer is: because it's not an error. It's only an error if
x
is false and if the caller uses the return value, neither of which
can necessarily be determined by the compiler, at least in the general
case.
In this particular case (returning a pointer), it wouldn't be too
difficult to require a return
for all paths; Java does this. In
general, however, it's not reasonable in C++ to require this, since in
C++, you can return user defined types for which it may be impossible to
construct a value (no default constructor, etc.) So we have the
situation where the programmer might not be able to provide a return
in a branch that he or she knows can't be taken, and the compiler can't
determine that the branch can't be taken.
Most compilers will warn in such cases, when it can determine the flow. All of the ones I've seen also warn in some cases where it's clearly impossible to fall off the end, however. (Both g++ and VC++ warn about:
int
bar( char ch )
{
switch ( ch & 0xC0 ) {
case 0x00:
case 0x40:
return 0;
case 0x80:
return -1;
case 0xC0:
return 1;
}
}
, at least with the usual options. Although it's quite clear that this function never falls off the end.)
As far as I remember, Visual Studio 2008 warns you about a "execution path that does not have a return value". It is allowed in the meaning of that "C++ won't stop you from shooting you in the foot". So you are to think, not the compiler.
What the standard says about this kind of programming is that it produces undefined behavior.
Undefined behavior is the joy and pity of C/C++, but it is also a fundamental feature of the language design that allows for many of the low-level optimizations that make C a sort of "high level assembler" (it is not, actually, but just to give you an idea).
So, while redirecting to John's answer about the switch to use with GCC, to know "why" the standard does not prevent that, I would point to a very interesting analysis of undefined behavior and all of its misteries: What Every C Programmer Should Know About Undefined Behavior. It makes for a very instructive reading.
精彩评论