问题
Every function call is executed on the stack and this function is deallocated from the stack memory after the function exits.
Suppose a variable "return_value" is declared as non-static(normal unsigned int) in a function foo(). At the end of the function foo(), this value is returned as
return return_value
This value should have been deallocated from the stack memory. Therefore,how does the main function that is receiving this return value get the correct value returned by foo()?
回答1:
With one exception, when a function returns a value, that value is returned in one of the machine's registers (or the equivalent). By the time the function is returning, the function's local storage (stack frame) is no longer needed to store the return value; the return value is copied out of a local variable into the return register if necessary.
The exception is functions that return pointers. If a function returns a pointer, and if the pointer value it decides to return points to local (stack frame) data, that's a big problem, because by the time the function has returned, that memory isn't really valid any more, and so the returned pointer value is useless.
Examples:
Function returning a simple constant value:
int f1() {
return 4; /* constant value 4 copied to return register */
}
Function returning value of a local variable:
int f2() {
int i = 5;
return i; /* value copied from i to return register */
}
Function returning a pointer:
int *f3() {
int i = 5;
return &i; /* WRONG: returns pointer to local storage */
}
Function returning a string:
char *f4() {
char str[] = "Hello, world!";
return str; /* WRONG: returns pointer to local storage */
}
A modern compiler will warn you if you try to return a pointer to local storage, as in f3()
or f4()
.
Actually, there's another exception, sort of, when it comes to functions that return structure values. Structures can be arbitrarily large, so a structure return value won't necessarily fit into any of the machine's registers. But the C language definition says that you are allowed to return structure values from functions and have it work properly, so the compiler has to do some extra work for you to make sure that there's some safe place to transport the return value back to the caller.
For example, suppose you write
struct person {
char firstname[100];
char lastname[100];
};
struct person f5() {
struct person ret;
strcpy(ret.firstname, "Akshay");
strcpy(ret.lastname, "Immanuel");
return ret;
}
This might look dangerous (especially if you remember how the earlier example f4()
didn't work), but it turns out it's 100% perfectly okay.
[Footnote. Actually, of course, my example is dangerous in a different way, in that it does not check for overflow when using strcpy
to copy strings into firstname
and lastname
.]
Suppose you call this function from somewhere else:
struct person x;
x = f();
How does this work? Well, it depends on the compiler; different compilers do it different ways. One way is that the compiler essentially pretends that you had written your function differently. It pretends that you had written
void f5(struct person *retp) {
struct person ret;
strcpy(ret.firstname, "Akshay");
strcpy(ret.lastname, "Immanuel");
*retp = ret;
}
And then when you call it, it pretends that you had written
struct person x;
f5(&x);
But the point is that you don't have to write it that way; the compiler does all that for you invisibly, behind your back.
回答2:
For simple small types such as integers, float types and pointers, the value is returned in machine rregister.
For complex types such as structures, the caller reserves the space on the stack and the callee stores the result there. As the caller is responsible for freeing the frame, it's up to it when to process the result.
One note: even structure can be returned in registers ss long as it fits. But it depends on platform and ABI specification.
来源:https://stackoverflow.com/questions/35100462/return-value-of-function