为什么链表要用双重指针??

什么事双重指针?

在C语言中,二重指针是指指向指针的指针。它的语法形式是type **ptr,其中type是指针指向的数据类型。二重指针通常用于函数参数传递,特别是在需要修改指针指向的内存地址时非常有用。

为什么一定要用双重指针?

在链表中使用双重指针的原因是因为malloc,要将malloc创建的内存的头指针传递下去。

1.正常情况下使用malloc函数

int main()
{
	int *p = (int *)malloc(sizeof(int));
	*p = 100;
	free(p);
	p = NULL;
	return 0;
}

使用malloc来创建地址,将创建的内存的首地址给指针变量*p;

最后free(p);来释放。

2.如果在局部函数中使用malloc函数,并不使用free

在C语言中,如果你在函数内部分配了内存并将其地址存储在一个指针中,那么当函数执行完毕并返回时,函数内部的局部变量(包括指针)将会被销毁,但指针指向的内存块不会被自动释放,它们仍然存在于堆内存中。

然而,如果你只是简单地在函数内部分配了内存给一个指针,并且该指针是一个单重指针,那么在函数返回后,你将无法访问到这块内存,因为指针已经失效了。

但是,如果你在函数内部使用了双重指针,并且通过它来操作内存,即使函数返回后,通过双重指针间接访问到的内存块仍然存在,因为指针所指向的内容在堆上分配,而不是在函数的栈帧中。因此,使用双重指针能够在函数外部保持对分配的内存块的引用,以便后续的操作或释放。

下面是一个简单的示例,演示如何声明、分配内存和使用二重指针:

在这个示例中,allocate_2D_array函数接受一个二重指针作为参数,通过分配内存为二维数组并将其地址存储在传递的指针中。然后,main函数调用allocate_2D_array函数来分配内存给myArray,并在之后释放了这些内存。

#include <stdio.h>
#include <stdlib.h>

// 函数原型,接受一个int型的二重指针作为参数
void allocate_2D_array(int rows,int **array) {
    // 分配内存给一维数组
    *array = (int *)malloc(rows * sizeof(int));
    for (int i = 0; i < rows; i++) {
        (*array)[i] = i;
}
}

int main() {
    int *myArray; // 声明一个二重指针

    int rows = 3;
    

    // 调用函数,将分配的一维数组的地址存储在myArray中
    allocate_2D_array(rows, &myArray);

    // 打印一维数组
    printf("一维数组:\n");
    for (int i = 0; i < rows; i++) {
       
            printf("%d\n", myArray[i]);
    }
    free(myArray);
    return 0;
}

这是一个用malloc创建一个指针的例子。

在函数

// 函数原型,接受一个int型的二重指针作为参数
void allocate_2D_array(int rows,int **array) {
    // 分配内存给一维数组
    *array = (int *)malloc(rows * sizeof(int));
    for (int i = 0; i < rows; i++) {
        (*array)[i] = i;
}
}

中;

*arrar指向malloc创建的内存的首地址。但是当allocate_2D_array调用接受时,因为没有free,所以那么当函数执行完毕并返回时,函数内部的局部变量(包括指针)将会被销毁,但指针指向的内存块不会被自动释放,它们仍然存在于堆内存中。

然而,如果你只是简单地在函数内部分配了内存给一个指针,并且该指针是一个单重指针,那么在函数返回后,你将无法访问到这块内存,因为指针已经失效了。

但是,如果你在函数内部使用了双重指针,并且通过它来操作内存,即使函数返回后,通过双重指针间接访问到的内存块仍然存在,因为指针所指向的内容在堆上分配,而不是在函数的栈帧中。因此,使用双重指针能够在函数外部保持对分配的内存块的引用,以便后续的操作或释放。

再看一看链表,你应该就明白了

//建立带表头结点的单链线性表L(尾插法)
void CreateList(Node **L) 
{
	Node *p,*r;
	datatype ch;
	ch=getchar();
	*L = (Node *)malloc(sizeof(Node)); 
	r=*L;                                /* r为指向尾部的结点 */
 	while(ch!='@')
 	{
		p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */
		p->data = ch;           
		r->next=p;                        /* 将表尾终端结点的指针指向新结点 */
		r = p;                            /* 将当前的新结点定义为表尾终端结点 */
		ch=getchar();
	}
	r->next = NULL;                       /* 表示当前链表结束 */
}

就是想让CreateList(Node **L)调用完成时,将malloc的首地址保存下来,所以使用Node **L。通过双重指针间接访问到的内存块仍然存在,因为指针所指向的内容在堆上分配,而不是在函数的栈帧中。

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值