佛科院计算机软件技术基础——指针与二重指针详解

一、引入——指针与子函数的关系:

  1. 什么是指针?

指针是一种特殊的变量,类似于一般的变量存放着数据,指针存放着地址,通过这个地址可以指向空间,从而操作该空间内的数据

  1. 普通变量、指针变量在子函数中不同表现:

#include "stdio.h"
void swi_normal(int a,int b);
void swi_point(int *a,int *b);
void main()
{
    
    int a=1,b=2;
    //分别用普通变量和指针变量进行操作,并打印出结果
    swi_normal(a,b);
    printf("normal:a %d b %d\n",a,b);
    swi_point(&a,&b);
    printf("point:a %d b %d\n",a,b);
}
//普通变量操作
void swi_normal(int a,int b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
//指针变量
void swi_point(int *a,int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

(1)结果:

通过第一个操作,a,b交换失败;而第二个操作,a,b交换成功

(2)分析:

因为第一个函数是传入数据,然后在子函数中在进行申请空间来存放数据,子函数结束后会自动释放这些空间;第一个函数是传入地址,子函数结束后不会释放这些空间

二、推广到二重指针:

  1. 以建立顺序表为例:

#include "stdio.h"
#include <stdlib.h>
#define datatype int
#define MAXSIZE  4
typedef struct
{
    datatype data[MAXSIZE];        //存储顺序表中的元素
    int len;                        //顺序表的表长
}SeqList;                             //顺序表类型


void CreatList_Normal(SeqList *L);
void CreatList_Point(SeqList **L);
SeqList *Init_SeqList();
void main()
{
    SeqList *L1,*L2;
    //初始化
    L1 = Init_SeqList();
    L2 = Init_SeqList();
    //输入数据
    CreatList_Normal(L1);
    CreatList_Point(&L2);
    //打印输入后的情况
    printf("Normal:%d  %d  %d\n",L1->data[1],L1->data[2],L1->data[3]);
    printf("Point: %d  %d  %d\n",L2->data[1],L2->data[2],L2->data[3]);
}

SeqList *Init_SeqList()
{
    SeqList *L;
    L=(SeqList*)malloc(sizeof(SeqList));
    L->len=0;
    return L;
}

void CreatList_Normal(SeqList *L)
{
    int i, n;
    printf("Input length of List: ");
        scanf("%d", &n);
    printf("Input elements of List: \n");
    for(i=1;i<=n;i++)
        scanf("%d", &L->data[i]);
    L->len=n;
}


void CreatList_Point(SeqList **L)
{
    int i, n;
    printf("Input length of List: ");
        scanf("%d", &n);
    printf("Input elements of List: \n");
    for(i=1;i<=n;i++)
        scanf("%d", &(*L)->data[i]);
    (*L)->len=n;
}

(1)结果:

(2)分析:

两种方式没有区别,因为顺序表的结构体中只含有数据,只需要指向这些数据的地址就可以改变了,所以只需要一重指针。

  1. 以建立链表为例:

#include <stdio.h>
#include <stdlib.h>
#define datatype char
typedef struct node
{
    datatype data;            //data为结点的数据信息
    struct node *next;      //next为指向后继结点的指针
}LNode;                                  //单链表结点类型

void CreateLinkList_Normal(LNode *head);
void CreateLinkList_Point(LNode **head);
void main()
{
    LNode *L1,*L2;
   //对L1初始化,使L1存有某空间地址
    L1 = (LNode *)malloc(sizeof(LNode));
     //分别建立链表
    CreateLinkList_Normal(L1);
    CreateLinkList_Point(&L2);
}
void CreateLinkList_Normal(LNode *head)
{                       //将主调函数中指向待生成单链表的指针地址(如&p)传给*head
    char x;
    LNode *p;
    head=(LNode *)malloc(sizeof(LNode)); //在主调函数空间生成链表头结点
    head->next=NULL;        //*head为链表头指针
    printf("L1 Input: \n");
    scanf("%c", &x);      //结点的数据域为char型,读入结点数据
    while(x!='\n')             //生成链表的其他结点
    {
        p=(LNode *)malloc(sizeof(LNode));     //申请一个结点空间
        p->data=x;
        p->next=head->next;       //将头结点的next值赋给新结点*p的next
        head->next=p;                //头结点的next指针指向新结点*p实现在表头插入
        scanf("%c", &x);            //继续生成下一个新结点
    }
}

void CreateLinkList_Point(LNode **head)
{                       //将主调函数中指向待生成单链表的指针地址(如&p)传给**head
    char x;
    LNode *p;
    *head=(LNode *)malloc(sizeof(LNode)); //在主调函数空间生成链表头结点
    (*head)->next=NULL;        //*head为链表头指针
    printf("L2 Input: \n");
    scanf("%c", &x);      //结点的数据域为char型,读入结点数据
    while(x!='\n')             //生成链表的其他结点
    {
        p=(LNode *)malloc(sizeof(LNode));     //申请一个结点空间
        p->data=x;
        p->next=(*head)->next;       //将头结点的next值赋给新结点*p的next
        (*head)->next=p;    //头结点的next指针指向新结点*p实现在表头插入
        scanf("%c", &x);            //继续生成下一个新结点
    }
}

(1)结果:

(2)分析:

我们可以看到L1的数据没有发生变化,还是刚初始化好的值,L2的数据发生了改变,为什么会这样呢?

单链表结点类型中包含了一个指针变量,在顺序表中我们只需要指向整型变量就行,而在链表中我们需要指向指针变量next,类似于第一个例子,我们要改变指针变量的值就要传指针变量的地址进去,我们就要用到指针的指针(地址的地址)——二重指针

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值