对传递引用感到困惑
考虑以下示例,我尝试以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版本的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; }
现在它工作,输出为1,就像我预期的那样。 但是,我不明白为什么。 我有点困惑为什么在顶部分层额外的指针解决了我的问题。
谢谢!
C没有传递引用。 除数组外,所有参数都按值传递。
在您的第一个版本中,您将按值传递变量。 在increment
函数中,它分配内存并将其分配给局部变量number
。 但这对调用者的变量没有影响,因为只传递了它的值,而不是对变量的引用。 因此,当increment
返回时, thing
仍然未初始化,并且通过它的间接导致未定义的行为。
如果函数需要修改调用者的变量,则调用者必须传递指向变量的指针,而不仅仅是值。 这就是你在第二个版本中所做的。 然后函数可以通过指针间接更新变量。
当你在C ++中使用引用时,这基本上就是在幕后发生的事情。 在C中,您必须明确地编写额外的间接级别。
也许你正在寻找的是这样的:
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
包含main
的thing
的地址。 那么你可以改变指向的number
(即thing
),然后当你返回的thing
被修改了。
这与你的第二个例子略有不同,因为没有动态内存分配,我认为这是你的目标。
在示例的上下文中通过引用传递意味着将指针传递给对象。
指针本身就是程序中的对象
int main() { unsigned* thing; //...
因此,要通过引用传递此对象类型unsigned*
,您必须传递指向此对象的指针
void increment(unsigned** number); int main() { unsigned* thing; increment(&thing); //...
我想如果引入一个typedef会更清楚。 想象一下下面的例子
typedef unsigned* T; void increment( T* number); int main() { T thing; increment( &thing ); //...
我希望现在更清楚了。:)
您发布的第二种方式是正确的方法。 第一种方法不起作用的原因是,当number
实际上已经通过值传递时,您试图修改number
。 因此,尽管事实上你已经通过引用传递了变量的thing
,但是thing
的地址已经传递给值increment
。