再谈怎么理解双指针 **

    技术2023-03-29  17

    原文出处http://blog.csdn.net/feiyinzilgd/archive/2011/01/14/6138438.aspx

     之前我写过一篇博客《深入理解双指针》,最近也再次重温《C++ Primer》读到指针那一章节的时候,度C/C++指针又有了新的领悟。

    《C++ Primer》中强调了一个指针解引用的概念。

    究竟什么是解引用呢?

    为了解释解引用这个概念,我引用《C++ Primer》中的一段话:

    When we dereference a pointer, we obtain the object to which the pointer points

    从上面这段话可以看出解引用的对象是指针,当我们对指针解引用的时候,我们得到的是指针所指向的对象。按照C语言的习惯,当我们队指针解引用的时候,我们得到的是该指针所指向的结构。

    举个例子:

    view plaincopy to clipboardprint?int idata = 24;   int *ptr = &idata;//定义一个指针指向idata     /**这里就是对指针ptr解引用     解引用之后得到ptr所指向的结构,也就是idata,赋值给getdata  */  int getdata = *ptr//“*”星号就是用来解引用的  int idata = 24;int *ptr = &idata;//定义一个指针指向idata

    /**这里就是对指针ptr解引用   解引用之后得到ptr所指向的结构,也就是idata,赋值给getdata*/int getdata = *ptr//“*”星号就是用来解引用的

    一级指针: C/C++中,变量或者结构都有一个作用域。

    要想在作用域B中修改作用域A中的非指针变量的值(比如 int 数据),就必须将该变量的指针传入到作用域B中,

    然后对指针解引用,然后作出任何修改都会反馈到该指针所指向的数据,否则值传递无法反馈修改结果,即修改是无效的。

    view plaincopy to clipboardprint?//version 1   void swap(int param1, int param2){       int tmp = param1;       param1 = param2;       param2 = tmp;   }   void funcA(){              int a = 24;       int b = 12;       swap(a, b);   }  //version 1void swap(int param1, int param2){    int tmp = param1;    param1 = param2;    param2 = tmp;}void funcA(){        int a = 24;    int b = 12;    swap(a, b);}

    上面version1代码,作用于funcA中的变量直接值传递到作用域swap中,由于param1,param2的作用域仅限于swap。

    所以,对param1, param2的任何修改都不会反馈到funcA中,所以,a和b不会有任何变化。

    所以,为了使非指针变量的值能够在不同的作用域中进行修改并反馈结果到不同域中,那就是用一级指针(为了区别后面要重点讲述的双指针)吧,然后对指针解引用,之后修改的任何结果都会被反馈到不同的域中。

    view plaincopy to clipboardprint?//version 2   /**  对指针ptr1和ptr2解引用之后,作出的任何修改都会反馈到指针所指向的数据中去  */  void swap(int *ptr1, int *ptr2){       int tmp = *ptr1;       *ptr1 = *ptr2;       *ptr2 = tmp;   }   void funcA(){       int a = 24;       int b = 12;       swap(&a, &b)//传入a和b的指针   }  //version 2/**对指针ptr1和ptr2解引用之后,作出的任何修改都会反馈到指针所指向的数据中去*/void swap(int *ptr1, int *ptr2){    int tmp = *ptr1;    *ptr1 = *ptr2;    *ptr2 = tmp;}void funcA(){    int a = 24;    int b = 12;    swap(&a, &b)//传入a和b的指针}

    上面version 2中,就是用了一级指针,对指针解引用之后,对其作出的任何修改都会反馈到指针所指向的数据。

    所以,a和b的数据发生了变化。

    双指针 view plaincopy to clipboardprint?//version 3   /**  getbufer函数想让getmemory函数申请一块内存并将内存起始指针赋值给  buffer这个指针  */  void getmemory(char *ptr){       ptr = (char *)malloc(20);//这个地方对ptr解引用没有任何意义。因为我们是为了修改指针本身,而不是修改指针所指向的值                          }    void getbuffer(){       char *buffer = NULL;       getmemory(buffer);   }  //version 3/**getbufer函数想让getmemory函数申请一块内存并将内存起始指针赋值给buffer这个指针*/void getmemory(char *ptr){    ptr = (char *)malloc(20);//这个地方对ptr解引用没有任何意义。因为我们是为了修改指针本身,而不是修改指针所指向的值                    } void getbuffer(){    char *buffer = NULL;    getmemory(buffer);}

    上面version 3的代码,我们想要修改buffer本身这个指针的值,但是getmemory(buffer)之后,buffer的值还是NULL,并不是所希望的那个molloc之后堆中那个起始地址。

    分析如下:

    ptr的作用于在getmemory中,虽然我们传入了buffer这个指针,但是由于ptr是局部变量,对ptr做修改无法反馈到getbuffer域中

    所以,为了使指针变量的值(不是指针变量所指向的值)能够在不同作用域中进行修改并反馈修改结果,使用双指针吧,然后传入需要修改的指针的地址,然后对解引用作出的任何修改都将反馈到该指针。

    双指针定义和申明:

    int **p从这个申明中就可以知道,指针的指针,p所指向的值也是一个指针,即p指向的值也是一个地址。

    然后对P解引用: *p

    之后,对*p的任何操作都将反馈到p所指向的地址的值,从而达到对指针本省的修改

    view plaincopy to clipboardprint?//version 4     void getmemory(char **p){       *p = (char *)malloc(10);   }   void getbuffer(){       char *buffer;       getmemory(&buffer);   }  //version 4

    void getmemory(char **p){    *p = (char *)malloc(10);}void getbuffer(){    char *buffer;    getmemory(&buffer);}

    对指向非指针变量的指针[指针的内容是非指针变量的地址](其实就是该变量的地址)进行解引用,作出的修改可以反馈到该指针所指向的值,这里的值是非指针变量。 对指向指针变量的指针[指针的内容指针变量的地址]进行解引用,作出的任何修改可以反馈到该指针所指向的值,这里这个值是指针变量本身的值(不是指向的值)。 综合1和2可以得出一个结论:对解引用之后的任何操作,都将反馈给该指针所指向的值。而这个值可以分为指针变量和非指针变量。

    什么时候使用双指针?       回答:当我们需要修改指针变量本身的值的时候,可以使用双指针

    很多情况下,双指针都可以通过其他途径,比如使用return来反馈结果。

     

    本文来自博客,转载请标明出处:http://blog.csdn.net/feiyinzilgd/archive/2011/01/14/6138438.aspx

    最新回复(0)