链表为什么有些情况下要使用二重指针

链表

一个疑问

  • 今天在复习链表时遇见了几个问题,其实是拖了很久的问题,现在尝试分析一下

    结构体:
    typedef struct Node{
      int data;
      struct Node *next;
      }Node;
    
    main()
      Node *list=NULL;
      CreatNode(list);
      printf("%d",list->data);
    
    Node * CreatNode(Node *head)
      {
          Node * pNew=(Node *)malloc(sizeof(Node));
          pNew->data=0;
          pNew->next=NULL;
          head=pNew;
      }
    

    在主函数里,定义了一个Node类型的指针并赋值NULL,然后调用CreatNode函数试图用一个新的节点来对它赋值,以完成对第一个节点的初始化操作。

    本以为会输出0,但结果却是程序崩溃了,为何?

    先把这个问题放一边,来看另一段代码:

    main()
    {
        Node *list=NULL;
        list=CreatNode()
    }
    Node * CreatNode()
      {
          Node * head=(Node *)malloc(sizeof(Node));
          head->data=0;
          head->next=NULL;
          return head; 
      }
    

    这段代码可以成功运行,对比前一段代码,可以看到如下不同:

    • 后一段代码是list来接收返回值,前一段是将list当成参数传入

    但为啥运行结果天差地别呢?

分析:第二种情况用list接收一个返回值,这是一定能成功的,。在函数中malloc了一个Node空间,然后将其地址返回,如此list的值就等于这个Node的地址了;

第一种情况是将list作为参数传入,我们知道,一旦涉及参数,就会有形参和实参,也就是说会有一个list的副本。这个副本和实参在数值上相等,但地址不同,所以如果在函数里修改这个副本的值是没有办法同步到实参的,只能通过地址来操作值才能使形参和实参同步。因此,传了list之后,会有一个形参list,它们的值(现在是NULL)相同,但地址不同。
   
而我们是想改变主函数中list的值,那么在函数中直接修改值肯定是不行的,那只是修改了副本的值,等函数执行完毕后,副本(在这个程序里是head)和pNew都会被回收。所以这么做不仅达不到修改主函数中list值的目的,反而还会造成内存泄漏( 因为,副本和pNew都被回收,没有其他指针指向申请的内存空间了 )。

  • 其实想一想是很简单的,想要在函数里改变变量的值我们就得传地址;想要改地址的值,我们就得传地址的地址。在这个例子里面,我们不过是想改变主函数中指针的值而已,自然得传指针的地址。正确的代码如下:

    main()
    Node *list=NULL;
    CreatNode(&list);
    printf("%d",list->data);
    
      Node * CreatNode(Node **head)
      {
          Node * pNew=(Node *)malloc(sizeof(Node));
          pNew->data=0;
          pNew->next=NULL;
          *head=pNew;
      }
    
  • 2020年1月5日于实验室,这几天想复习一下指针,正好看到链表这里,于是想起了此前一直被困扰的问题。其实不难,只不过是被指针给绕晕了,本质上还是传值和传址。

  • 关于二重指针可以接着看这篇加强理解:https://blog.csdn.net/qq_39579087/article/details/104812065

  • 19
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值