简体   繁体   中英

How do C++ progs get their return value, when a return is not specified in the function?

I recently wrote a post:
Weird Error in C++ Program: Removing Printout Breaks Program

...in which I was trying to solve a seemingly baffling problem, in which removing a cout statement would break my program.

As it turned out, my problem was that I forgot to return my true/false success flag that I was later using for logic.

But apparently SOMETHING was being returned and that something was always true if I left that cout in, but would seemingly "magically" become false when I took it out.

My question for you all is:

Obviously forgetting your return type is a bad idea. In this case, though, it was largely due to the nature of my program -- a quick hack job. I later decided that it wasn't worth the effort to include implement an algorithm to determine the success/failure of the function call -- but accidentally left behind the code dependent on the return.

Bafflingly g++ gave me no warnings or errors when compiling the executable like so:

g++ main.cc -g -o it_util

My version is: g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)

Again, to save others future frustration in case they make the same silly mistake and are met with the same seemingly erratic behavior, can anyone cast light on where a function without a return gets its return value from??

Thanks!!

There is no logic to it, and most C++ compilers should flag it with a warning. It allowed for backward-compatibility to C.

In K&R C, there was no void type, and when a type was unspecified, it default to int . So,

myfunc() {....}

Was techincally a function returning a int, but most programmers used that form for a routine not returning a value.

The compiler had to make sense of this. So, the convention became, the return would put something into a register. And the assignment in the calling routine would take the value out of the register. Now, if the callee never issued a return, nothing specific would be placed in that register. But it would still have some (random) value in it, which would be blindly assigned in the caller.

On x86 calling conventions, the return value for integers and pointers is on the EAX register. The following is an example of that:

int func() {
    if(0) return 5; // otherwise error C4716: 'func' : must return a value
}
int main() {
    int a;
    a = func();
}

Compiling with cl.exe /Zi , MSVC++10:

push    ebp
mov     ebp, esp
push    ecx
call    j_?func@@YAHXZ  ; func(void)
mov     [ebp+a], eax ; assumes eax contains the return value
xor     eax, eax
mov     esp, ebp
pop     ebp
retn

Of course, this is all undefined behavior.

From C++ Standard section 6.6.3 The return statement

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

There is one exception (as per 3.6.1/5):

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

The reason this is syntactically allowed is put nicely by James Curran . But with the -Wall gcc option (as commented by Neil) you should be warned on this behavior; something like 'Not all control paths return value in a value-returning function...'.

It depends on the calling convention. For instance, for a 32-bit integer return on an Intel platform, you get whatever is in the eax register.

With a modern compiler you'll probably get an Warning using -Wall

But if you don't return a value, usually you'll get garbage.

"What determines what a c++ function return when no return command is executed within the function? Is there any logic to it?"

The type in the beginning of the function.

Example:

int cow() { int temp; return temp; }

If you don't return the correct type or return nothing, the compiler should complain. Edit: Oh crap, I've just read your flags. You need to turn on more flags man, -W -Wall -pedantic. Read the g++ manual.

Unless you have a void function. Then you don't have to return anything or you can have pointer to play.

void somefunction( int* ptr_int) { int temp = *ptr_int; temp +=1000; this->ptr_int = temp; }

I believe the above code works, it have been awhile since I've coded in C++.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM