display | more...
I suppose it's common nowadays to think of return values as objects, but the reality is that a return value is nothing more than a number in a register.

It doesn't 'go' anywhere, because it isn't a 'thing' that needs to exist such as matter or energy, it is a mere symbol or cipher. It can be destroyed.

When you don't use the returned value of a function it simply sits around until the spot it's being stored in is reused for some other representation.

If you'd like to consider it in absolute physical terms, however, there is an electrical charge pattern sitting in a bank of transistors into which the function places this number. The electrical charges come from other portions of the processor, and ultimately from a power source, such as a battery or a generator.

Since these registers are often implemented in a symmetric fashion, a one is simply a positive charge on one transistor, while a zero is a positive charge on its twin. Thus it doesn't matter what representation is stored in that logic cell, if it doesn't change no charge is lost (excepting leakage current), and when it does change a charge is lost and one is gained.

These charges are dumped straight to ground, or, in other words, head right back to the power source.

Of course, we could go into the whole "Charge is represented by moving electrons, which actually pass from negative to positive, therefore charge actually starts out at ground and makes it way back to the top of the processor where it spews from the power pins into the power source."

But I find it confuses computer scientists.

Electro-existentialism notwithstanding, different languages handle the problem of return-value bookkeeping in different ways, from functions being subroutines which don't return a value (any data modified by the subroutine must be somehow available by reference to the subroutine) to functions which exist solely for their return value, prohibiting side-effects (modification of out-of-scope data by in-scope references).

Okay, something in English, now, eh? Let's suppose we have a function that returns an integer. And let us also suppose that we are able to pass this function a reference (or, pointer) to a memory location we wish it to modify. And let us further suppose that the return value is always going to be zero. (I know, I know, it's bad programming practice. Slap me on the wrist, mama, I write functions like this all the time!) Now, of course we don't care what the return value is. So suppose we write it in The One True Language like so:

int    foo(char **string) {
    string   = do_something_with_string(*string);
    return 0;
    }

char *string = "Yobaby!";

foo(&string);

We can track the normal case within foo(), as the return value of do_something_with_string() is assigned to string. do_something() computes a value and returns it. That value (in this case, a pointer to a new version of the original string) is assigned to string. Then the variable string falls out of scope at return() and is destroyed, while the data created lives on in the location referenced by the **string argument.

Lost yet? Sorry . . . I'll try to be a bit more clear. The new version of the original string is still in existence, though it has not been returned by foo(). The return value of foo() does exist, and is written to a location in memory pending an assignment. However, since no assignment is performed, it falls out of scope and is placed in the bit bucket for reuse.

So, that, in far too many words, is where unassigned return values go. Limbo. Hades. The Great Bit Bucket in the Sky. The Beyond. The Happy Hunting Grounds.

Now, malloc()'ed memory for which you lose all pointers? Well, the compiler can only cut you so much slack . . . we call that a memory leak. (And yes, there have been languages, though thankfully none of any currency that I know of — though I may be mistaken — which require you as the programmer to explicitly dispense with return values, or they won't go out of scope until the end of the block in which the function was called. Now that's what I call annoying!

Note: So as not to be redundant, I purposely didn't make this writeup all-inclusive. See also function, return value, malloc, pointer, bit bucket if any of my assumptions are unfamiliar to you.

Log in or register to write something here or to contact authors.