Why does flowing off the end of a non-void function without returning a value not produce a compiler error?

后端 未结 9 2313
粉色の甜心
粉色の甜心 2020-11-21 07:37

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 co

相关标签:
9条回答
  • 2020-11-21 08:23

    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).

    0 讨论(0)
  • 2020-11-21 08:24

    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 the main 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

    Flowing off the end of a function [...] results in undefined behavior in a value-returning function.

    § 3.6.1/5

    If control reaches the end of main without encountering a return statement, the effect is that of executing

    return 0;
    

    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.

    -Wreturn-type Warn whenever a function is defined with a return-type that defaults to int. Also warn about any return statement with no return-value in a function whose return-type is not void (falling off the end of the function body is considered returning without a value), and about a return statement with an expression in a function whose return-type is void.

    This warning is enabled by -Wall.


    Just as a curiosity, look what this code does:

    #include <iostream>
    
    int foo() {
       int a = 5;
       int b = a + 1;
    }
    
    int main() { std::cout << foo() << std::endl; } // may print 6
    

    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.

    0 讨论(0)
  • 2020-11-21 08:25

    In some limited and rare cases, flowing off the end of a non-void function without returning a value could be useful. Like the following MSVC-specific code:

    double pi()
    {
        __asm fldpi
    }
    

    This function returns pi using x86 assembly. Unlike assembly in GCC, I know of no way to use return to do this without involving overhead in the result.

    As far as I know, mainstream C++ compilers should emit at least warnings for apparently invalid code. If I make the body of pi() empty, GCC/Clang will report a warning, and MSVC will report an error.

    People mentioned exceptions and exit in some answers. Those are not valid reasons. Either throwing an exception, or calling exit, will not make the function execution flow off the end. And the compilers know it: writing a throw statement or calling exit in the empty body of pi() will stop any warnings or errors from a compiler.

    0 讨论(0)
提交回复
热议问题