【问题标题】:passing linked list to function by value按值传递链表给函数
【发布时间】:2021-04-08 18:47:57
【问题描述】:

编辑:我的结构是这样的:

         struct node{
             int key;
             struct node* next;
         }
         typedef struct node* LIST;

我正在编写一个名为print_list_iteratively 的函数,它采用单链表并以相反的顺序迭代地打印其元素。让我把我的 3 个函数放在下面,然后解释一下我的问题是什么?

         LIST reverse_list(LIST L) {
              LIST current = L, prev = NULL, subsequent = NULL;
              while (current != NULL) {
                // first we need to get the next element to not lose the link.
                subsequent = current->next;

                // now reverse the pointer
                current->next = prev;

                // we need to update our prev to create link between the currrent and next element.
                // in short, we need to get the address of current node
                prev = current;

                // finally update the current
                current = subsequent;
             }
             return (L = prev);
        }

上面的代码将链表L反转,返回链表L的新头部。

        void print_list(LIST L) {
             while (L) {
                printf("%d  ", L->key);
                L = L->next;
             }
        }

print_list 按连接顺序打印列表中的元素。

前面提到的print_list_iteratively函数我都需要写了。

        void print_list_iteratively(LIST l) {
            // first reverse the list, then call print_list. that's all.
            printf("address of function parameter is %p\n", l);
            l = reverse_list(l);
            print_list(l);
        }

我对这些功能没意见;它们按预期工作,但是当我试图理解函数如何将列表作为参数并返回它时,按值传递和按引用传递的概念让我感到困惑。让我简单地写一个 main 来测试这些,我们会看看事情是如何混合起来的。

         int main(void) {
             l = insert(l, 5);
             l = insert(l, 10);
             l = insert(l, 15);
             l = insert(l, 45);
             print_list(l);
             print_list_iteratively(l);
             print_list(l);
             return 0;
         }

当第一个print_list 函数被调用时,它会打印5->10->15->45. 下一个print_list_iteratively 在列表l 上被调用,它又在函数体中调用reverse_list 和print_list。 print_list 内 print_list_iteratively 给出反向列表 45->15->10->5. 最终,print_list 内主要打印 5.
我想知道为什么第二个print_list 刚刚打印了5?我已经将列表发送到 print_list_iteratively 传递值,而不是传递引用,尽管如此,它改变了我原来的列表 insinde main 函数。有人能解释一下这个例子中的列表是如何传递给函数的,以及它们是如何从函数中返回的吗?感谢您的回答。

【问题讨论】:

  • current->next = prev; 该代码更改了原始列表。您按值传递了头指针,但它不会阻止更改列表字段。
  • typedef struct node* LIST; 在 typedef 后面隐藏指针会导致代码混乱。看起来您正在传递一个值,但您正在传递一个指针。我建议将其更改为typedef struct node LIST; 并传入LIST *。
  • 风格问题:不要在 typedef 中隐藏指针,所以使用typedef struct node LIST;。大写单词通常保留给宏,因此将LIST 重命名为例如tList。
  • @kaylum,谢谢,知道了。让我再问一个关于按值传递列表头的问题。在我的过程 reverse_list 中,我按值获取原始列表的头并将其分配给 L,但此分配只是将头指针的值复制到 L。列表 L 与我的主函数中的列表相同,但因为我没有'不发送我的原始列表的地址,L 不指向原始列表指向的位置。但是,当操作完成时,head 会受到函数更改的影响,因为最初它们都具有相同的 head 值。
  • @kaylum,函数对该地址进行了操作,这就是我原来的列表发生变化的原因,对吧?很高兴能得到你的想法。

标签: c pointers pass-by-reference singly-linked-list pass-by-value


【解决方案1】:

问题是你通过值传递头指针。这让您的程序可以修改您的链表,但头指针保持不变。

您应该通过引用或指向您的指针的指针将头指针传递给函数。 (node*& or node**) 请记住,如果您通过指针传递它,则需要在需要时取消引用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 2021-07-16
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    相关资源
    最近更新 更多