【问题标题】:insertion in linked list -插入链表 -
【发布时间】:2015-06-10 19:38:40
【问题描述】:

我在读 Skeina 的书。我无法理解这段代码。基本上双指针有什么用。还有*l = p有什么用?谁能用图解释一下。

void insert_list(list **l, item_type x) {
    list *p; /* temporary pointer */
    p = malloc(sizeof(list));
    p->item = x;
    p->next = *l;
    *l = p;
}

【问题讨论】:

  • 这不是 C++(不能在没有强制转换的情况下使用 malloc,如果必须使用原始指针,则应在 C++ 或 new 中使用智能指针)。
  • @VladfomMoscow 现在 c 在没有 struct 关键字的情况下还能工作吗?
  • @crashmstr:你不需要在 C 中转换 malloc 的结果。
  • @πάντα ῥεῖ 是的,如果您使用 typedef,它就可以工作。:)
  • @rost0031 我知道,我没有说你需要将结果转换为 C。我说因为没有转换 malloc它不可能是 C++,这是它最初的标记方式。

标签: c pointers linked-list


【解决方案1】:

您不应将其称为“双指针”,因为那将是指向double 的指针。它是指向指针的指针,用于允许函数更改恰好是指针的参数的值。如果您熟悉 C#,它就像一个 out 参数。在这种情况下,l 参数用于获取 IN 和 OUT 行为,但您可能经常看到它仅用于输出。

由于这个函数返回类型void,它很可能在不使用指向这样的指针的情况下编写:

list * insert_list(list *l, item_type x) {
{
    list *p; /* temporary pointer */
    p = malloc(sizeof(list));
    p->item = x;
    p->next = l; // note that this is not *l here
    return p;
}

此更改将需要调用该函数的代码更新它自己的列表句柄,因为列表的头部是正在更改的内容。

【讨论】:

    【解决方案2】:

    这个函数执行一个非常简单的任务:它插入一个list 节点到 它接收指针的位置。没有什么 双指针的特别之处,它们只是指向指针的指针。它们持有一个指针的地址,其中包含一个对象的地址。 void **l 包含 list * 指针的地址。 *l 检索 这个地址和*l = p 存储它。

    malloc 用于分配一个 list结构,p接收分配结构的地址。 代码有些草率,因为p 之前没有检查过NULL 取消引用它。如果malloc 因内存不足而失败,则 程序将调用未定义的行为,希望以 分段错误或可能更糟糕的事情。

    节点被初始化,它的next指针被设置为指向的节点 通过l 参数,最后存储新节点的地址 在作为l 参数传递的地址处。效果很简单:在*l处插入节点。

    这个方法很聪明,它允许相同的函数在列表的任何地方插入一个新节点。例如:

    list *head = NULL;
    ...
    /* Insert a LIST_A node at the beginning of the list */
    insert_list(&head, LIST_A);
    ...
    /* insert a LIST_B element as the second node in the list */
    insert_list(&head->next, LIST_B);
    ...
    /* find the end of the list */
    list *node;
    for (node = head; node->next; node = node->next)
        continue;
    
    /* insert a LIST_Z node at the end of the list */
    insert_list(&node->next, LIST_Z);
    

    上面唯一棘手的是指针本身的概念,这里简单概述一下:

    • 内存可以概念化为(大)字节数组,地址是该数组中的偏移量。
    • char 变量定义为单字节,
    • int 变量占用特定于系统架构的多个字节,在当前硬件中通常为 4 或 8 个字节。
    • 将指针视为保存另一个变量内存地址的变量。它们需要足够大以容纳系统中的任何有效地址,在当前具有超过 4 GB 物理和可寻址内存的系统中,它们是 64 位长并占用 8 个字节。
    • 有一个特殊的地址值NULL,它不代表任何对象,用于指定给定指针不指向任何真实对象。地址0 用于此目的。 malloc 将返回 NULL 如果它无法分配请求的内存,则应测试返回值,因为在此地址存储值是被禁止的,并且通常被视为无效访问(分段错误)。

    此摘要有意简化。我使用术语 variable 而不是 object 以避免与 OOP 概念混淆。

    【讨论】:

    • @blue boy:感谢响应者的正确方式是支持他们的答案并接受最有帮助的答案。
    猜你喜欢
    • 2017-08-27
    • 2013-02-28
    • 2016-06-04
    • 2020-06-28
    • 1970-01-01
    • 2012-02-18
    相关资源
    最近更新 更多