zoukankan      html  css  js  c++  java
  • 关于“指针的指针”的认识(值传递、指针传递区分)

    【摘要】对于C语言的參数传递通常都是值传递。当传传递一个指针给函数的时,事实上质上还是值传递。我们能够看以下常见的面试题:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void function1(int *v)
    {
         v = (int *)malloc(sizeof(int));
         *v = 100;
    }
    
    void main()
    {
         int *v = NULL;
         function1(v);
         printf("%d
    ",*v);
    }

    分析:指针事实上本质就是一个变量。存放的是地址。只是也是一个值罢了,仅仅只是特殊一点。本段函数的被调函数就把这个值(也就是地址)拷贝了下来。

    被调函数运行了 v = (int *)malloc(sizeof(int)); 之后,这样一条语句主动申请一块内存,并把这块内存的地址返回给v 。悄然把地址改动啦。这时主函数和被调函数中的指针指向的东西没有半毛关系了,主函数中v还是NULL,所以……

    1、指针传递与值传递

    我们再来看以一个交换2个数的值的函数调用的代码:

    void swap ( int *a, int *b ){
        int c;
        c = *a;
        *a = *b;
        *b = c;
    }
    int main(int argc, char **argv){
        int a,b;
        a = 16;
        b = 32;
        swap( &a, &b);
        return ( a - b );
    }
    

    分析:能够正常交换a,b的值,被调函数操作的*a变量解引用一下,事实上它的地址和主调函数a是一样的。因此它们操作是在同一块内存区域。能够实现数值的交换。

    以下贴出一个错误的代码:

    void swap ( int *a, int *b ){
        int *temp;
        temp = NULL;
        temp = a;
        a = b;
        b = temp; 
    }
    int main ( int argc, char **argv ){
        int a,b;
        a = 16;
        b = 32;
        swap(&a, &b);
        return ( a - b );
    }
    

    分析:这样的方式依照理论上来说。是想通过调用swap函数,在swap函数内部。实现将交换&a,&b,即交换a和b的地址来达到目的。

    可是被调函数仅仅是对a,b的地址进行拷贝,简单一点说事实上就相当于值传递。即使被调函数再一次对a,b地址进行改动,对主调函数实參a,b地址是没有不论什么影响的。所以根本没有起到值交换目的的。

    所以上述代码是错误的,无法实现你想要的功能。

    2、指针的指针

    当我们用二级指针来实现上述功能的时候有就能够达到效果。

    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void swap ( int **a, int **b ){
        int *tmp = NULL;
        tmp = *a;
        *a = *b;
        *b = tmp;
    }
    
    int main ( int argc, char **argv ){ 
    
        int x = 16; 
        int y = 32; 
        int *a = &x;
        int *b = &y;
    
        swap(&a, &b); 
    
        printf("%d
    ",*a-*b);
        getchar();
    
        return 0; 
    
    } 
    

    分析:这个时候,你会发现就能实现达到交换的目的。我们通过操作中间桥梁(一级指针 *a)通过交换它们的值,实现数值交换。

    3、指针的指针常见用途

    双指针主要用在但我们想向一个A函数传递參数的时候。可是我们希望在A内部对參数做不论什么改动都能保存起来,那么就是用双指针吧。

    举个样例;
    我们在做链表的时候,我们肯定希望在用一个函数creatLink(…)函数来添加链表节点。

    那么我们能够有2种方法来实现
    第一种,用一级指针

    typedef struct node{
        ...
        ...
    }list;
    node *create(list *l){
       list *head;
       head = l;
       malloc...//为节点申请内存空间
       ...
       ...
       //操作
       return head;
    }
    int main(...){
        ...
        ...
        list *listhead
        createList(listhead);
        ....
        //以后的不论什么操作。我们都要考虑,我们是否拿到的是链表头指针,究竟哪
        是链表波的头指针,我们是否要return下来返回链表头指针??
    }
    

    分析:这样做能够达到添加节点的目的。可是,在不论什么情况下。我们的操作都得死死地抓住头指针,也即是我们添加节点后,不论什么对链表长度的改动,我们都要 链表头指针返回,即 return head;所以,我们要通过这个函数最后获得头指针,抓住他,死死地抓住他,然后操作。

    另外一种方法:用双指针,也即是二级指针。

    typedef struct node{
        ...
        ...
    }list;
    void create(list **l){
       list *head;
       head = l;
       malloc...//为节点申请内存空间
       ...
       ...
       //操作   
    }
    
    int main(...){
        ...
        ...
        list *st
        createList(st)
        ....
        ..
    //以后的不论什么操作。无论是删除还是插入,我们不须要考虑。我们是否已经return head了。不须要。我们在不论什么情况下,对链表的操作都仅仅须要使用st来完毕,由于,st就是链表的头指针。不变。由于在申明st的时候,已经为st分配 一个地址空间,它是存在的,一直存在,直到main函数结束
    }
    

    这里有关于指针的指针两篇不错的博客。推荐给大家
    深入理解双指针的两种使用方法
    又一次认识二级指针(Pointers to Pointers)

  • 相关阅读:
    Support依赖库大全
    反射调用泛型
    会爬行的小乌龟
    改进版——使用了双缓冲技术
    启动运行发现窗体不能最大化,添加
    添加图层
    实现放大,缩小,漫游,复位等功能
    从上一个项目中我得到的反思
    ​Error -4075: File not found. An error occurred merging module <MODULENAME> for feature <FEATURENAME>.
    总结—angularjs项目
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7298160.html
Copyright © 2011-2022 走看看