C语言学习知识点(六)——二重指针概念及其应用

来源:互联网 发布:光伏功率优化器 编辑:程序博客网 时间:2024/05/06 14:28

二重指针就是指向指针的指针。

其声明原型为:

[cpp] view plain copy
  1. datatype ** variable_name;  

假设我们声明并定义了三个变量:

[cpp] view plain copy
  1. int a = 1; /*整数类型变量*/  
  2. int *b;     /*整数类型指针*/  
  3. b = &a;    /*赋值,指向a*/  
  4. int **c;   /*二重指针*/  
  5. c = &b;    /*指向b*/  

打印a,b,c的值:

[plain] view plain copy
  1. a=1,b=002CF784,c=002CF778请按任意键继续. . .  

首先声明并定义了整数类型变量a,其值为1。然后定义了指针变量b,并指向a,因此b的值为变量a的地址。同理,c的值为指针变量b的地址。因此,有了二重指针变量,我们可以分别获得b 和 a 的值。 *c为b的值(该值为a的地址),**c为a的值(1)。

对于一个链表来说如果只是遍历,直接传入函数遍历即可(一维指针就可以了),加入我们想要对链表进行插入或者删除等操作(特别是对头尾进行修改时),那就必须用到二重指针了(**)

原理类似于下面的程序及讲解

#include"stdio.h"

void fun(char * pa)
{
    printf("pa的值:%d\n",pa);
    pa = "bb";
    printf("pa的值:%d\n",pa);
}

int main(void)
{
     char * p = 0;
     printf("p的值:%d\n",p);
     fun(p);

     if(p != 0)
     {
          printf("改变后输出p = ");
          puts(p)
     }
     else
     {
          printf("p值未改变!\n");
     }
    
     return 0;
}

结果输出"p值未改变!",分析一下不难理解:给fun函数传参的时候,其实应该是有一个隐形的操作pa=p ,这个操作和普通的两个变量赋值是一样的,把p的值赋给了pa,
然后,我们通过打印出来的值可以看到,在fun里面,pa的值原本是p的地址的,但是,pa在fun里面指向了“bb”,这样,问题就出来了,pa的值确实改变了,指向也变了,
但是,我们想要改变的p的值仍旧是”0“。
后来,我发现,p的值没有改变是因为pa改变的是他自己的值,没有改变他的指向的地址的值,但在这个例子里面作为参数的p初始化是0,也就是NULL,如果进行*pa = 'b'
这样的操作的话是非法的。    为了使操作成功,我给p赋了初值”aa“,然后进行这个操作发现仍旧不成功。原来,因为计算机的内存主要是分为:栈区、堆区、静态区、只读
区,其中,栈区,分配的是局部变量空间,比如是函数的调用,局部变量,需要执行的代码等等一些不需要我们手动分配和释放的内存;堆区,是向上增长的,主要是分配程序员申请的空间;静态分区,分配的是静态变量、全局变量;只读分区,分配的是常量和代码空间。    所以,这个操作才会失败。。

现在,来总结一些:首先,我们需要的结果是通过传递一个指针,来改变这个指针的指向的值,上面那个例子里面,传递的仅仅是一个地址值,因此,在下面的例子里面,我们需要传递的是一个完整的指针变量,我把这个指针变量的地址传进去,这就是我理解的二重指针做参数:
#include"stdio.h"

void fun(char ** pa)
{
    printf("pa的值:%d\n",pa);
    *pa = "bb";
    printf("pa的值:%d\n",pa);
}

int main(void)
{
     char * p = 0;
     printf("p的值:%d\n",p);
     fun(&p);

     if(p != 0)
     {
          printf("改变后输出*p = ");
          puts(p);
     }
     else
     {
          printf("p值未改变!\n");
     }
    
     return 0;
}

OK,把指针p的地址作为参数传递给fun函数,pa=&p;*pa="bb";这样就可以p的值就变成"bb"在只读区的地址了。。。




阅读全文
0 0