我发现这个链接列表例程(来自Haviland的Unix系统编程)将一个项目添加到单个链接列表中。
additem(item **head, item *newitem)
{
newitem->next = *head;
*head = newitem;
}
我的困难在于试图理解item **head
部分。 **head
到底意味着什么?为什么不用item *head
定义例程如下:
additem(item *head, item *newitem)
{
newitem->next = head;
head = newitem;
}
答案 0 :(得分:3)
它是指向指针的指针。
在C中,您无法更改按值传递的变量,因为参数将作为局部变量处理。您必须改为传递指针,然后修改*variable
的值。
当您要更改的变量已经是指针时,它也适用。在这种情况下,您必须将指针传递给该指针,因此当您更改此指针时,此更改将传播到调用方。
*head
是head
指向的值。虽然head
的类型为item **
,但*head
的类型为item *
。
执行此操作时:
additem(item *head, item *newitem)
{
newitem->next = head;
head = newitem;
}
修改head
的值不会影响它对调用者的值。出于所有目的,在此上下文中更改head
毫无意义。
答案 1 :(得分:1)
您的标题中有第一个问题的答案:item **head
表示head
是指向指针的指针。
为什么您的第二个代码段不起作用?因为
head = newitem;
将值分配给本地变量head
,这不是代码的目的。
答案 2 :(得分:1)
答案 3 :(得分:0)
如果您只是将指针*head
传递给子例程并更改其值并尝试返回它,您将发现不能,因为它是传递给例程的值,该例程仅存在于例程的堆栈中例程在范围内。但是,您可以将指针传递给该指针(**head
,它也将在堆栈中是本地的),并更改它指向的值,然后在范围中更改要更改的值调用例程实际上已经改变了。
这是实现call-by-reference的'C方式',即使C只正式支持call-by-value - 它使用一个值为call-by-value,其值是对你想要的东西的引用改变,从而允许通过引用进行调用。
答案 4 :(得分:0)
只是简单地理解:如果你想要另一个函数来改变变量的值。您必须传递其地址,因为C使用"按值" 机制调用。
void change_value(type *a)
{
*a = ...;
}
在这种情况下,您希望将指针的值更改为 head 类型(head *),因此其addr的类型为head **
输入* a 等于(head * )* a 或 head ** a