Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C and C++ functions without a return statement [duplicate]

Tags:

c++

c

return

While looking through code at work I found some (seemingly) offensive code in which a function had a return type, but no return. I knew the code worked, but assumed it was just a bug in the compiler.

I wrote the following test and ran it using my compiler (gcc (Homebrew gcc 5.2.0) 5.2.0)

#include <stdio.h>

int f(int a, int b) {
  int c = a + b;
}

int main() {
   int x = 5, y = 6;

   printf("f(%d,%d) is %d\n", x, y, f(x,y)); // f(5,6) is 11

   return 0;
}

Analogous to the code I found at work, this defaults to returning the result of the last expression executed in the function.

I found this question, but was not satisfied with the answer. I know that with -Wall -Werror this behavior can be avoided, but why is it an option? Why is this still allowed?

like image 424
erip Avatar asked Sep 11 '15 00:09

erip


People also ask

What does a function with no return statement return?

If no return statement appears in a function definition, control automatically returns to the calling function after the last statement of the called function is executed. In this case, the return value of the called function is undefined.

Can we declare a function without return type in C?

If you do not specify a return type or parameter type, C will implicitly declare it as int .

Do C functions need a return?

In the example above,the function returns an int. Some languages differentiate between "subroutines", which do not return a value, and "functions", which do. In C there are no subroutines, only functions, but functions are not required to return a value.

Which function must not use a return statement?

In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value. You may or may not use the return statement, as there is no return value.


1 Answers

"Why is this still allowed?" It is not, but in general, the compiler cannot prove you are doing it. Consider this (of course extremely simplified) example:

// Input is always true because logic reason
int fun (bool b) {
    if (b) {
        return 7;
    }
}

Or even this one:

int fun (bool b) {
    if (b) {
        return 7;
    }
    // Defined in a different translation unit, will always call exit()
    foo();
    // Now we can never get here, but the compiler cannot know
}

Now the first example could flow off the end, but it never will as long as the function is used "properly"; and the second one could not, but the compiler cannot know this. So the compiler would break "working" and legal, although probably stupid, code by making this an error.

Now the example you posted is a little different: Here, all paths flow off the end, so the compiler could reject or just ignore this function. It would however break real world code that relies on the compiler specific behavior as in your production code, and people do not like that, even if they are wrong.

But in the end, flowing off the end of a non-void function still is undefined behavior. It might work on certain compilers, but it is not and never was guaranteed to.

like image 179
Baum mit Augen Avatar answered Oct 14 '22 10:10

Baum mit Augen