【问题标题】:Difference between struct * and struct ** in function header函数头中struct *和struct **的区别
【发布时间】:2019-04-10 16:07:58
【问题描述】:

我正在尝试用 C 解决我的家庭作业,该作业要求我创建一个函数,将 char 值放在排序链表中的正确位置。 实际上我并没有真正理解函数头在 struct typedef name *structstruct typedef name **struct 之间的区别。

当我查看老师的解决方案时,她使用** 这样做了,但不明白这是什么意思。

void insert_in_sorted_list(Node *lst, char x) {
    Node *temp;
    while (lst) {
        if (x > lst->value && x < lst->next->value) {
            temp = (Node*)malloc(sizeof(Node));
            temp->value = x;
            temp->next = lst->next;
            lst->next = temp;
        }
        else lst = lst->next;
    }
}

【问题讨论】:

  • int* = 这是 int 的内存地址 int** = 这是包含 int 内存地址的内存地址
  • 当您的函数显示时,您无法更改列表中的第一项(lst),因为您需要更改指针指向的内容,然后您需要指针的地址才能更改它。与foo(int* n) { *n = 1; }比较,这里只有n指向的东西,而不是指针本身

标签: c struct linked-list


【解决方案1】:
  • struct - 是一个在某处占用内存的数据对象。
  • struct* - 是指向该内存块的指针
  • struct** - 是指向该内存块的指针! (是的,现在很混乱)

如果你将一个结构体传递给一个函数,因为每个函数都有一个副本,你不能改变原始数据。因此,您通常将指针传递给结构,这意味着您所做的任何更改都将应用于原始数据。即,您不更新按值副本,而是就地更新旧的内存结构。

但是,有时还没有结构(例如,因为您想在函数中构造一个),因此无法告诉调用者您将这个新结构放在哪里。所以你必须传递一个** 来表示“我已经创建了这个结构,它就在这里”,然后将该位置传递给调用者。即,您指向创建结构的内存,并通过“指向”参数技巧将该位置传回。

你不能简单地传递一个指向结构的指针,因为它是按值传递给函数的,即复制。所以当函数退出时,旧的指针值被保留。因此是指针对指针。

指针在概念上很尴尬,恕我直言,将它们视为包含内存位置(它们实际上是)的整数值,而不是试图将它们理解为一些抽象概念。这也可以很好地理解诸如性能和内存复制之类的事情。

【讨论】:

    【解决方案2】:

    考虑它的简单方法是 * &lt;something&gt; 表示指向某物的指针,而 '** ` 表示指向某物的指针。

    由于 c 是按值传递的,因此“更改”参数的唯一方法是传递指向它的指针。

    所以带有 ** 的函数会改变函数中指针指向的内容。

    【讨论】:

      【解决方案3】:

      当您接受带有* 的参数时,您实际上是在接受某物的地址(这称为指针)。如果您接受带有** 的参数,则您接受的是指向指针的指针。

      所以这个:

      void insert_in_sorted_list(Node *lst, char x)
      

      正在接受指向Node的指针

      还有这个:

      void insert_in_sorted_list(Node **lst, char x)
      

      正在接受指向Node的指针。

      如果我们已经创建了一个列表并且我们没有添加到列表的前面或后面,那么您的实施将起作用。但是请考虑如果您需要更改列表中的第一项可能会发生什么。如果用户有一个指向列表中第一个节点的指针并将其传递给函数,并且新节点需要插入到第一个节点的前面,则函数可以将它正确地插入到第一个节点的前面但是当用户查看在使用此函数后的列表中,他们仍然会有一个指向同一 Node 的指针(不应再是第一个),并且不知道它前面存在一个节点。所以用户需要传递一个指向第一个节点的指针,这样就可以改变指向第一个Node的指针。

      更新您的代码以接受指向 Node 的指针的指针,现在您需要使用 *lst 访问指向节点的指针,而不仅仅是 lst

      void insert_in_sorted_list(Node ** lst, char x)
      

      要考虑的另一件事是,如果用户有一个空列表,则不会插入任何内容。

      考虑如果我们到达最后一个节点会发生什么,即lst-&gt;next 为NULL,当我们尝试访问lst-&gt;next-&gt;value 时,我们会遇到某种NULL 指针异常。即使我们没有,这段代码是否会在最后插入另一个节点?

      【讨论】:

      • 是的,你的权利。我试图思考为什么函数会被传递Node ** list 而不仅仅是Node * list 我唯一能想到的是一个数组,我没有仔细观察OP 发布的实现。编辑了那部分。
      猜你喜欢
      • 2017-08-08
      • 2011-03-13
      • 2011-11-14
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-09
      • 2014-06-17
      • 1970-01-01
      相关资源
      最近更新 更多