Function without return values.


R. Clayton (rclayton@monmouth.edu)
(no date)


I have a recursive function that returns an int. In one of the branches I
forgot to return a value, but my program compiled and worked correctly. Why is
that?

  This is an unhappy legacy from C. C did not require that functions explicitly
  return a value.

    $ cat t.c
    #include <stdio.h>
    int f() { }
    int main() { printf("%d\n", f()); }

    $ gcc t.c

    $ ./a.out
    133388

    $ cc t.c

    $ ./a.out
    133640

    $

  If a function doesn't have an explicit return value, then the value that
  happens to be in the return register is the function's return value.

  C++, being a descendant of C, keep that disreputable feature.

    $ cat t.cc
    #include <iostream>
    int f() { }
    int main() { std::cout << f() << "\n"; }

    $ g++ t.cc

    $ ./a.out
    134920

    $

  However, some C++ compilers are more strict than others.

    $ CC t.cc
    "t.cc", line 2: Error: "f()" is expected to return a value.
    1 Error(s) detected.

    $

  And almost all compilers have options that will warn you of functions without
  explicit returns.

    $ cc -v t.c
    "t.c", line 2: warning: Function has no return statement : f
    "t.c", line 3: warning: Function has no return statement : main

    $ gcc -Wall t.c
    t.c: In function `f':
    t.c:2: warning: control reaches end of non-void function
    t.c: In function `main':
    t.c:3: warning: control reaches end of non-void function

    $ g++ -Wall t.cc
    t.cc: In function `int f()':
    t.cc:2: warning: control reaches end of non-void function

    $

  There is no warning about main() in the last example because standard C++
  requires that main() with no explicit return statment always returns a 0.

  In your case, you lucked out. Becuase your function is making recursive
  calls, the return value from the previous call is still in the return
  register, and that value served as the return value for the calls that didn't
  explicitly return a value.

    int f(int n)
      if n < 0
        return 0
      else
        f(n - 1)

  Unfortunately, you can't depend on that behavior; the compiler is allowed to
  make any changes it wants to registers between calls, including changing the
  contents of the return register. This code also depends on the fact that the
  return value didn't change between calls (it's always 0). If this code had
  to change the return value, then your program wouldn't have worked.



This archive was generated by hypermail 2.0b3 on Thu Dec 18 2003 - 16:15:05 EST