struct node *head 和 struct node **head 之间有什么区别?

7

我正在尝试对链表进行排序。我对何时使用struct node *head和何时使用struct node **head感到困惑,这两种实现方法都可以实现。

应该在什么情况下使用:

void sortedinsert(struct node **head)

我应该在什么情况下使用:

void sortedinsert(struct node *head)
10个回答

15

使用以下函数签名:

void changeNode(struct node *head)
你拥有指向该节点的指针,因此你可以更改该结构。但你无法改变变量head所指向的内容。假设struct node 的定义如下:

你有一个指向节点的指针,因此你可以修改该结构。但你不能改变变量head所指向的内容。假设struct node的定义如下:

struct node
{
    int field1;
    struct node *next;
}

考虑到给定的函数签名和struct node,以下操作可以在该函数中更改结构:

void changeNode(struct node *head)
{
    head->field1 = 7;
    head->next = malloc(sizeof(struct node));
}

C语言是按值传递的:当我们将变量传递给函数时,函数获取到的是该变量的一个副本。这就是为什么我们传递一个指向struct node的指针,以便我们可以更改它,并且在函数外部看到这些更改的效果。但是,我们仍然只得到指针本身的副本。因此,以下操作是没有用的:

void changeNode(struct node *head)
{
    // we're only changing the copy here
    head = malloc(sizeof(struct node));
}

head 的更改不会在函数外反映出来。为了改变 head 指向的内容,我们必须使用额外的间接层:

void changeNode(struct node **head)
{
    // now we're changing head
    *head = malloc(sizeof(struct node));

    // alternately, we could also do this:
    *head = NULL;
}

现在对 head 进行的更改会在函数外部得到反映。


3
你传递的是指针 head 的地址,这使得它可以指向不同的内存区域。 使用struct node *head无法将head修改为指向其他地方。

2

首先,这是一个指向结构体节点的指针。

(struct node *) head;

head定义为一个变量,它可以存储node的地址。

这允许在方法中通过引用传递node

第二个是指向结构体node的指针的指针。

(struct node **) head;

head定义为一个变量,它可以存储另一个变量的地址,该变量具有node的地址。

这允许在方法中通过引用传递node *


2
如果head始终指向链表头部(一个常量位置),则使用struct node* head。 如果您计划更改head指向的位置,则使用node **head。

你也可以通过从任何能够更改它的函数中返回一个新值并将其结果分配来更改head。(请参见我的回答) - Antimony

1
案例1:当您使用以下内容时:

void sortedinsert(struct node **head)

在这个函数内部,你将会实际修改头指针,因为你很可能会在内部使用*head。sortedinsert 函数很有可能会被调用并传入参数 &head。
情况2:当你使用:
void sortedinsert(struct node *head)

在该函数内,您将修改head指针的副本,因为您很可能会在内部使用head变量。sortedinsert函数很可能会使用head参数调用。

0
在这个例子中,由于head的值可能会发生变化(它可以指向与当前节点不同的其他节点),因此在创建时应该使用。
void sortedinsert(struct node **head)

由于您的头部可能需要修改。

而且下面的原型似乎需要更改,

void sortedinsert(struct node *head)

由于这不允许您修改头部,所以在这种情况下应该是这样的(如果您正在使用此功能),

struct node * sortedinsert(struct node *head)

该函数返回更新后的头部,可供调用该函数的程序使用。


0

运行或阅读此内容,您可以看到它

#include <stdio.h>
struct node{
    int one;
    int two;
    struct node * next;
    //char location[100];
};
void changeHead(struct node** head){

}
void sort(struct node* head){

}
int main(){
    struct node* head = (struct node*) (malloc (sizeof(struct node)));

    // now head pointing to a node stucture ( if you dereferance head you get teh first value)

    struct node* tmp = head;

    struct node** newHead = (struct node**) (malloc (sizeof(struct node*)));

    //New head points to a 'struct node*', which hold an addtess of another struct node

    head->one = 12;//*head->one =12; //head.one = 12 is wrong cos it is holding an address.
    // you can do it but it doesnt make sence since you dont know whats on address #12


    // now if you want head to point to old head which is on tmp at the moment
    *newHead = head;

    // now if you working with 2 linked list and you want to change the heads use below
    changeHead(newHead);

    // if you want to just sort its better and easy to use
    sort(head);

    //chack whats on head and newhead
    printf("double derefence newHead:%d\n",**newHead);
    printf("derefence newHead(its and address same ad address of head):%d\n",*newHead);
    printf("Head(its and address):%d\n",head);
    printf("derefence Head:%d\n",*head);//head->one works too
}

0
  1. 要更改指向第一个节点的头指针,您需要将头的地址(即(&head))传递给调用函数(因此在函数中声明了指向指针变量的指针(struct node**head),因为它接收指向第一个节点的指针(head)的地址。
  2. 但是,如果您知道头指针将保持不变,即您不希望头指针指向其他节点(例如..不在开头插入新节点),则只能传递(head)来调用函数,并在函数定义中写入((*head))

0

node* 是指向节点结构体的指针。 node** 是指向指向节点结构体的指针的指针。在 C 中,当您想通过引用修改指针时,会使用指向指针的指针。

假设您想对节点 B 进行操作,该操作可能会用不同的节点替换节点 B。一种方法是

nodeA.next = foo(nodeA.next);

另一个选择是只需执行

foo(&nodeA.next);

并且让foo隐式地替换nodeA.next指针。


0
简单来说,当您想要更改由 "head" 指向的位置时,请使用 **head,否则在不允许更改位置的情况下,请使用 *head

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接