一级指针与二级指针

通过学习C语言的精髓,指针,我们已经可以领略到内存的神奇。当然相对来说,也容易混淆一级指针与二级指针的某些地方,本文就个人理解,浅谈一下。

传值与传址(一级指针)

最初接触指针的时候,一个典型的案例就是传值与传址。主函数(为减少麻烦,本文均已主函数作为调用函数)与子函数的沟通是通过实参与形参的传递关系完成的。

传值中,主子函数关系为将实参的数值传给形参后,主子函数的实参与形参就毫无任何关系了,形参的任何变化均与实参无关。

传址中,主子函数关系为将实参的地址传给形参后,子函数的形参就能操控主函数中的实参数值的变化,故形参的变化可以影响到实参。

        此节较为简单,故不再举例说明,但依然很重要,因为这是最基础的知识点。假设传值中,实参为一个指针变量,若想达到指针变量数值的变化,要传送指针变量的地址,而指针变量本身就为地址,因此涉及到二级指针,看起来易与传址中的地址含义混淆,但是若能深刻理解传值与传值的思想,举一反三,非常容易理解。

指针的地址(二级指针)

下面的例子为单链表的建立以及将单链表逆转,其中链表的逆转需要更新头指针的指向,即更新变量内容,故需要传送其地址给子函数,因为其本身为地址,故需要二级指针变量接收地址的地址。为方便理解,可将head理解为一级指针中的普通变量。同理,如果建立单链表如果要传送head,亦需要传送指针的地址。(指针可以理解为地址等价)

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* next;
}Node;

Node* createList()
{
Node* head, *p,*q;
int n;
scanf("%d",&n);
p = (Node*)malloc(sizeof(Node));
head = p;
q = p;
while(n!=0)
{
p = (Node*)malloc(sizeof(Node));
p->data = n;
q->next = p;
q = p;
scanf("%d",&n);
}
q->next=NULL;
return head;
}

void reverseList(Node** head)
{
Node *p, *q, *r;
if((*head)->next==NULL)
return;
p=(*head)->next;
q=p->next;
p->next=NULL;
while(q)
{
r=q->next;
q->next = p;
p=q;
q=r;
}

r=(Node*)malloc(sizeof(Node));//新建一个指向首节点的头结点
r->next=p;
*head=r;
}

//带头结点的遍历
void display(Node* head)
{
Node* q;
q=head->next;
while(q!=NULL)
{
printf("%d\t",q->data);
q=q->next;
}
printf("\n");
}

int main()
{
Node* head;
head = createList();
display(head);
reverseList(&head);//想要改变head变量里面的数值,需传送head的地址
display(head);
return 0;
}

其结果显示为:      


若将逆转子函数改为如下代码:当然调用函数相应改为:reverseList(head);

void reverseList(Node* head)
{
Node *p, *q, *r;
if(head->next==NULL)
return;
p=head->next;
q=p->next;
p->next=NULL;
while(q)
{
r=q->next;
q->next = p;
p=q;
q=r;
}
r=(Node*)malloc(sizeof(Node));
r->next=p;
head=r;

}

想想结果是怎样的呢?结果变为下图所示,想想为什么呢?

因为head的内容没有改变,head依然指向头结点,头结点依然指向首节点,但是首节点的next变为了NULL,故只能输出1,后面的链表已经逆转。

那么有没有一种方法可以不使用用二级指针完成逆转呢,of course,不过肯定就不会改变head指向的内容了,也就是说当head依然指向头结点,而头结点指向逆转后的第一个首节点的时候当然就可以啦。

void reverseList(Node* head){Node *p, *q, *r;if(head->next==NULL)return;p=head->next;q=p->next;p->next=NULL;while(q){r=q->next;q->next = p;p=q;q=r;}head->next = p;//头结点指向逆转后的首节点} 

所以,为了统一方便,只要涉及到修改链表了,均使用二级指针。数据结构C语言实现版好像很多都是这样的哦,所以,最好的方法如下:

void reverseList(Node** head)
{
Node *p, *q, *r;
if((*head)->next==NULL)
return;
p=(*head)->next;
q=p->next;
p->next=NULL;
while(q)
{
r=q->next;
q->next = p;
p=q;
q=r;
}
(*head)->next= p;//头结点指向逆转后的首节点
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值