函数的返回值 [英] Return value of function

查看:101
本文介绍了函数的返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个函数调用都在堆栈上执行,并且该函数退出后,该函数从堆栈内存中释放。

Every function call is executed on the stack and this function is deallocated from the stack memory after the function exits.

假定变量 return_value声明为non功能foo()中的-static(普通无符号int)。
在函数foo()的末尾,此值返回为

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

该值应该已经从堆栈存储器中释放。
因此,接收此返回值的主函数如何获得foo()返回的正确值?

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()?

推荐答案

除了一个例外,当一个函数返回一个值时,该值将在计算机的寄存器(或等效值)之一中返回。在函数返回时,不再需要函数的本地存储(堆栈框架)来存储返回值;返回值将在必要时从局部变量中复制到返回寄存器中。

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.

示例:

返回简单常量值的函数:

Function returning a simple constant value:

int f1() {
    return 4;        /* constant value 4 copied to return register */
}

a的函数返回值局部变量:

Function returning value of a local variable:

int f2() {
    int i = 5;
    return i;        /* value copied from i to return register */
}

返回指针的函数:

int *f3() {
    int i = 5;
    return &i;       /* WRONG: returns pointer to local storage */
}

返回字符串的函数:

char *f4() {
    char str[] = "Hello, world!";
    return str;      /* WRONG: returns pointer to local storage */
}

现代编译器会警告如果您尝试返回指向本地存储的指针,例如 f3() f4()

A modern compiler will warn you if you try to return a pointer to local storage, as in f3() or f4().

实际上,对于返回结构值的函数,还有另一个例外。结构可以任意大,因此结构返回值不一定适合机器的任何寄存器。但是C语言定义说您 被允许从函数中返回结构值并使其正常工作,因此编译器必须为您做一些额外的工作,以确保有一个安全的地方可以运输返回值返回给调用方。

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.

例如,假设您写

struct person {
    char firstname[100];
    char lastname[100];
};

struct person f5() {
    struct person ret;
    strcpy(ret.firstname, "Akshay");
    strcpy(ret.lastname, "Immanuel");
    return ret;
}

这可能看起来很危险(尤其是如果您还记得前面的示例 f4()无效),但事实证明100%完全可以。

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.

[脚注。实际上,当然,我的示例以另一种方式很危险,因为在使用 strcpy 将字符串复制到 firstname <时,它不会检查溢出。 / code>和 lastname 。]

[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.

这篇关于函数的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆