使用指针指向什么点?

问题描述:

我在网站上找到了这个代码,用于在列表的开头插入一个节点到链表中。使用指针指向什么点?

void push(struct Node** head_ref, int new_data) 
{ 
/* 1. allocate node */ 
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 

/* 2. put in the data */ 
new_node->data = new_data; 

/* 3. Make next of new node as head */ 
new_node->next = (*head_ref); 

/* 4. move the head to point to the new node */ 
(*head_ref) = new_node; 
} 

这是呼叫 -

push(&head, 7); 

功能我的问题是,为什么通过传递地址的指针,然后随后在函数内部的地址提取的值走很长的路要走。 为什么我们不能简单地传递在函数指针head后来作出这样的分配 -

new_node->next=head_ref; 

+0

[Jagged array](https://en.wikipedia.org/wiki/Jagged_array) –

+2

因为该函数也改变了'head_ref'的值。由于'head'有指针类型,所以你需要传递'push'的指针指针来更新'head'的值。 –

+0

阅读[this](https://*.com/a/897400/971127) – BLUEPIXY

如果通过head而不是&head,行

(*head_ref) = new_node; 

将不得不改为

head_ref = new_node; 

然而,这将是该函数的局部变化。它不会改变调用函数中的head的值。有两个问题:

  1. 调用函数将永远不会得到一个工作列表。
  2. 函数中分配的内存将是内存泄漏。
+0

这解释了它!谢谢! – Vaibhav

+0

@Vaibhav,很高兴我能够帮助。 –

调用程序中的变量头是一个指向列表头部的指针。你需要一个指向这个变量的指针,以便在push()中更新它。所以你将一个指针传递给一个包含指针的变量,以便你可以更新该变量。

你也可以写代码如下:

struct Node* push(struct Node* head_ref, int new_data) 
{ 
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 
    new_node->data = new_data; 
    new_node->next = head_ref; 
    return new_node; 
} 

,并调用它,如下所示:

head = push(head, 7); 

它实现了完全一样的东西,即在头插入一个新节点然后将head更新为指向该新节点。但在我看来,这不会是一个好的解决方案,因为它允许push()函数的调用者忘记将返回的值分配给head,此时您将拥有孤立节点并最终导致内存泄漏。

+0

这不一定是更糟糕的解决方案,它只是增加了要求分配回报。通过将指针传递给指向类型...的指针,您可以拥有两全其美的优点(例如,可以灵活地执行)...返回指向添加的当前节点的指针(用于分配或立即使用)。只要你正确地更新列表引用':'',那么'技术上'不会比另一个'更正确' –

这一切都与您选择的编程风格有关。使用一组函数来操作列表会使程序在结构上合理。这样你可以使它更具可读性。如果您需要从多个位置操作相同的列表或操作多个列表,它也将避免剪切-n粘贴。

你组织你的功能的方式取决于你。我个人喜欢你的例子。在这种情况下,你只需要在参数中指定一个指向头部的指针。如果从函数返回它,则在程序中使用错误指针的风险更高。

'C'有足够的工具来编写任何类型的程序。但是有时你需要遵循特定的规则来应用它们,比如你的案例中的指针地址。不是很方便,但可靠,并证明可行。作为'C'程序员,你会很快习惯它。

你也可以看看有更好的工具,使这更方便的c + +。