对传递引用感到困惑

时间:2015-07-28 21:06:06

标签: c memory-management memory-leaks pass-by-reference

考虑以下示例,我尝试以C方式传递引用:

// Function prototypes
void increment(unsigned* number);

int main()
{
    unsigned* thing;
    increment(thing);
    cout << *thing;
    return 0;
}

void increment(unsigned* number)
{
    number = (unsigned*) malloc(sizeof(unsigned));
    *number = 1;
}

我在第cout << *thing行遇到程序崩溃。是的,我在这里使用C ++,但我想尝试传递引用的C版本,因为我的主项目在C中。

我通过更改代码修复了它,如下所示:

// Function prototypes
void increment(unsigned** number);

int main()
{
    unsigned* thing;
    increment(&thing);
    cout << *thing;
    return 0;
}

void increment(unsigned** number)
{
    *number = (unsigned*) malloc(sizeof(unsigned));
    **number = 1;
}

现在它正常工作,输出为1,就像我预期的那样。但是,我不明白为什么。我有点困惑为什么在顶部分层额外的指针解决了我的问题。

谢谢!

4 个答案:

答案 0 :(得分:4)

C没有传递引用。除数组外,所有参数都按值传递。

在您的第一个版本中,您按值传递变量thing。在increment函数中,它分配内存并将其分配给局部变量number。但这对调用者的变量没有影响,因为只传递了它的值,而不是对变量的引用。因此thingincrement返回时仍未初始化,并且通过它导致未定义的行为。

如果函数需要修改调用者的变量,则调用者必须传递指向变量的指针,而不仅仅是值。这就是你在第二个版本中所做的。然后函数可以通过指针间接更新变量。

当您在C ++中使用引用时,这基本上就是在幕后发生的事情。在C中,您必须明确地编写额外的间接级别。

答案 1 :(得分:1)

也许您正在寻找的是这样的:

void increment(unsigned* number);

int main()
{
    unsigned thing;
    increment(&thing);
    cout << thing;
    return 0;
}

void increment(unsigned* number)
{
    *number = 1;
}

在C中,所有函数参数都按值传递。因此,您无法更改函数中的值,并希望在调用者中反映出来。但是如果传入的值是指针,则可以更改它指向的内容。在此示例中,thing的地址传递给increment。然后在increment中,number包含thingmain的地址。那么您可以更改number指向的内容(例如thing),然后在您返回thing时进行修改。

这与你的第二个例子略有不同,因为没有动态内存分配,我认为这是你的目标。

答案 2 :(得分:1)

在示例的上下文中通过引用传递意味着将指针传递给对象。

指针本身就是程序中的对象

int main()
{
    unsigned* thing;
    //...

因此,要通过引用传递此类型thing的{​​{1}},您必须将指针传递给此对象

unsigned*

我认为如果引入typedef会更清楚。想象一下以下示例

void increment(unsigned** number);

int main()
{
    unsigned* thing;
    increment(&thing);
    //...

我希望现在更清楚了。:)

答案 3 :(得分:0)

您发布的第二种方式是正确的方法。第一种方法不起作用的原因是,当number实际上已通过值传递时,您尝试修改number。因此,虽然您实际上已通过引用将变量thing传递给increment,但thing地址已传递给{ {1}}按价值计算。