LearningCpp
LearningCpp

Reputation: 59

When the control flow off the end of a function without a return, why there is still a returned value?

#include <iostream>

int func(int &a,int &b){
    if (a>b){
        return 1;
    }
}

int main(){
    int a=4,b=12;
    std::cout<<func(a,b)<<std::endl;
}

I think a run time error should occur because a is smaller than b, and the return statement is skipped. But it actually outputs the value of b no matter how I change the value of b. Could you please tell me why?

Upvotes: 4

Views: 764

Answers (5)

shitpoet
shitpoet

Reputation: 467

This is happening because a result of functions (if the return type is int) is transferred using rax register of CPU. return keyword places its argument in this register and returns to the caller function. But there is also an implicit return keyword at end of any function in C/C++ (if there is no explicit return placed by a programmer). And this is why this function returns control flow to the caller function.

But contents of rax register should be treated in this case as random because the compiler can use it for any variable or even totally ignore it.

EDIT: Because this is an accepted answer I should add important information here that was correctly mentioned in other answers and comments:

eerorika and others say that omitting return in non-void function is UB (undefined behavior) and a compiler can do whatever it wants in this case. (I didn't fact-check this but I strongly believe it's true.)

Klaus added a helpful answer about compiler flags that aid one in detecting such UBs.

Pete Becker notes that there are many different CPU architectures with different registers. (One can even imagine a CPU without registers at all, for example, a fully stack-based CPU.)

But please note that my original answer was straight to the question, explaining what is going on. I think this has value. Yes, it's UB and yes, one better enables compiler warnings but we also can provide some explanations of what's really going on. It makes our understanding of programming and computers better.

Upvotes: 5

eerorika
eerorika

Reputation: 238461

it should detect a run time error

That is not the case. The behaviour is undefined.

It seems to be related the value of b, why is that happening?

Because the behaviour is undefined.

Upvotes: 7

Klaus
Klaus

Reputation: 25663

You should not suppress the compiler warnings!

gcc says:

main.cpp:35:1: warning: control reaches end of non-void function [-Wreturn-type].

As others already mentioned: Your program has UB! So read the warnings and fix your program accordingly!

it should detect a run time error

And there is no need for run-time error, as the error is visible during compile-time! The core language has no run-time errors at all. If you see some error messages during program execution, it is coming from library code like a called "terminate" from an exception or something else.

It is good to have all the warnings enabled and also sometimes helpful to run different compilers over the code to get most of warnings possible.

For gcc you could add:

-Wall -pedantic -Wextra

That enables a lot of warnings, but not all. There are still some warnings which are not addressed like: -Wsuggest-override

Upvotes: 3

Ison Thomas
Ison Thomas

Reputation: 99

In C++ if a function is declared to return a value but it doesn't, it is undefined behavior

Upvotes: 1

Quentin
Quentin

Reputation: 63154

Falling out of a non-void function without returning is undefined behaviour, there's nothing your program or the runtime "should" do in that case.

Upvotes: 5

Related Questions