C返回函数参数。为什么这样做?

时间:2018-03-31 06:53:03

标签: c

我不是一名C程序员,但我最近对此感兴趣。据我所知,在C函数中,参数是通过值传递的,这就解释了为什么v1没有改变。

我不明白的是为什么v2在stack_copy返回后具有正确的值。我的理解是函数args被放在堆栈上,应该在函数范围的末尾进行处理,所以我希望v2包含垃圾。

这里发生了什么?

注意:我在Windows上使用Visual Studio 2015编译器在OS上进行了测试,并在OSX上进行了操作。

#include "assert.h"

typedef struct {
    int x;
    int y;
    int z;
} Vec3;

Vec3 stack_copy(Vec3 v) {
    v.x = 3;
    v.y = 3;
    v.z = 3;

    return v;
}

int main() {
    Vec3 v1 = {7, 7, 7 };
    Vec3 v2 = stack_copy(v1);

    assert(v1.x == 7 && v1.y == 7 && v1.z == 7);
    assert(v2.x == 3 && v2.y == 3 && v2.z == 3);

    return 0;
}

3 个答案:

答案 0 :(得分:2)

我假设你知道C中“按值调用”的概念,即你不是在询问参数似乎是一个参考(C ++风格)。
否则,她就主题Parameter Passing in C - Pointers, Addresses, Aliases

是一个很好的问答

你对这个问题的关注点是返回结构类型的值 同样的事情发生在“出路”上,即将值复制回函数的返回值被分配给的任何内容。

结构类型值与其他任何值都没有区别。

我认为在查看此示例时您没有想到您的问题:

int stack_copy(int v) {
    v = 3;

    return v;
}

答案 1 :(得分:1)

您按值传递值就像通过值一样。当然,参数v被释放(至少在语义上是因为编译器可以使用RVO返回值优化来优化它),但是它的值被返回并复制到v2中。定义类型定义其可能的值,对于结构,它是元素类型的笛卡尔积。因此,返回Vec3只会返回三个整数的 pack

答案 2 :(得分:0)

你是对的,局部变量在堆栈上分配。

调用方法时,会将v1的副本推入堆栈,并且以下所有操作都会更改该确切对象。

但是,编译器还执行了一个额外的步骤来允许非原始返回值(结构):在调用方法时,会传递一个额外的指针。它指向来自调用者堆栈的地址,并且返回值直接写入该地址。这也可以防止其他副本,并被称为"返回值优化"。