精华内容
下载资源
问答
  • 主要介绍了C语言二级指针的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握理解二级指针的知识,需要的朋友可以参考下
  • 指针的概念  指针就是地址, 利用这个地址可以找到指定的数据  指针就是地址, 那么在使用的时候, 常常会简单的说 指针变量为指针  指针变量就是存储地址的变量  int *p1;// 申请了一个变量, 即在内存中开辟了一块...
  • 本文主要介绍C语言 二级指针,这里整理了C语言二级指针的基础资料并附有示例代码和实现结果,帮助大家学习理解相关知识,有学习的朋友可以参考下
  • 而在更改链表时,看的书上一般都是传入二级指针,因为这时候改变了指针的指向。但实际上,只要不更改头指针,只传入一级指针就足够了。 #include<stdio.h> #include<stdlib.h> #define MAXSIZE 20 ...

    在通过函数交换两个变量的值时,仅仅是交换了两个变量的值,并没没有改变指针的指向,因此传入的是一级指针。

    而在更改链表时,看的书上一般都是传入二级指针,因为这时候改变了指针的指向。但实际上,只要不更改头指针,只传入一级指针就足够了。

    #include<stdio.h>
    #include<stdlib.h>
    #define MAXSIZE 20
    typedef struct Node
    {
        int data;
        struct Node *next;
    }Node;
    typedef struct Node *LinkList; /* 定义LinkList */;
    // LinkList L 相当于传入头指针,LinkList *L 相当于传入头指针的指针
    int Init(LinkList L){
        L =(LinkList)malloc(sizeof(Node));
        L->next = NULL;
    }
    
    int main(){
        LinkList L = NULL;
        printf("%p\n", L);  // 0x0  
        Init(L);
        printf("%p\n", L);  // 0x0  
    }

    在上面的例子中,因为要修改指针的指向,所以要传入二级指针才行,传入指针本身函数返回之后并没有任何变化。

     

    展开全文
  • C语言二级指针的介绍和使用

    千次阅读 2017-02-24 16:02:58
    一、一级指针级指针的简单描述 ①一级指针是一种以存储其他变量地址为目的的变量。一个T类型的指针变量(一级指针)就是一个存储了某T类型值变量的内存地址的引用。 ②对指针的解引用(也就是*),是获取...

    一、一级指针

    一级指针的简单描述

    ①一级指针是一种以存储其他变量地址为目的的变量。一个T类型的指针变量(一级指针)就是一个存储了某T类型值变量的内存地址的引用。

    ②对指针的解引用(也就是*),是获取指针指向的内存空间中存储的值。

    ③当指针解引用做左值的时候,可以改变指针指向内存空间中存储的值。

    ④指针指向哪个变量,就将该变量的内存地址赋给该指针(用于指针变量做左值的时候)。

    ⑤改变指针变量的值(指针变量做左值时),就改变了该指针的指向。

    二、二级指针的相关介绍

            多级指针(pointer to pointer to)是指向指针的指针,二级指针是指向一级指针的指针。

    一级指针指向的是某个变量,也就是一级指针中存储的是某个变量的内存地址;二级指针指向一级指针,也就是二级指针中存储的是一级指针的内存地址。

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int  main( void )
    {
         int  a = 10;                         //声明一个变量a
         int  *p = &a;                        //声明指针p,指向变量a
         int  **q = &p;                       //声明二级指针q,指向一级指针p
         printf ( "a = %d\n" ,a);               //打印变量a的值
         printf ( "a的地址&a=%p\n" ,&a);         //打印变量a的地址
         printf ( "p = %p\n" ,p);               //打印p的值
         printf ( "p的地址&p=%p\n" ,&p);         //打印p的地址
         printf ( "p的解引用*p=%d\n" ,*p);       //打印p的解引用
         printf ( "q = %p\n" ,q);               //打印q的值
         printf ( "q的地址&q=%p\n" ,&q);         //打印q的地址
         printf ( "q的解引用*q=%p\n" ,*q);       //打印q的解引用
         printf ( "q的双重解引用**q=%d\n" ,**q);  //打印q的双重解引用
         return  0;
    }

    执行结果

    a = 10

    a的地址&a=0x7fff5fbff838

    p = 0x7fff5fbff838

    p的地址&p=0x7fff5fbff830

    p的解引用*p=10

    q = 0x7fff5fbff830

    q的地址&q=0x7fff5fbff828

    q的解引用*q=0x7fff5fbff838

    q的双重解引用**q=10

    内存结构示意图

    wKiom1Xz386jNEX9AAGufVXL4L4041.jpg

            如上图的代码和执行后的结果,从结果中就可以看出变量a,一级指针p和二级指针q的关系。

    在学习的过程中主要是对二级指针不是很理解,所以这里特别对二级指针说明一下。

    变量q是一个二级指针,里面存放的是一级指针p的地址,对q的解引用就得到了q所指向的一级指针的值,也就是变量a的地址,对q双重解引用就得到了变量a的值,所以也可以通过二级指针来修改变量a的值。


    三、指针与二位数组

            首先一点的是,虽然二维数组的数组名可以看做是一个指针,但是并不能将二维数组的数组名赋值给一个二级指针,也就是如下的代码

    1
    2
    3
    4
    5
    6
    int  main( void )
    {
         int  arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
         int  **p = arr;
         return  0;
    }

            上面的代码在执行的时候会报错,这是因为两者数据类型是不相同的,所以不能赋值。

    二维数组的数组名指向的是一维数组,也就是指向数组类型,但是二级指针指向的是一级指针,也就是指针类型,所以两者不能互相赋值。


    下面详细介绍指针与二维数组的关系

    声明一个二维数组

    int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

            要想理解指针和二维数组之间的关系,就要首先弄清楚各种数组名所代表的元素。

    对于二维数组的存储,是按照先行后列的形式排列的,把每一行看做是一个一位数组,那二维数组就是由多个一位数组组成的数组,即二维数组是数组的数组。

            对于二维数组名,可以将它看做是指向行数组的指针,也就是说二维数组的元素是行数组,所以对于二维数组加减的变化是以行数组的大小为单位的,即arr指向arr[0]这个行数组,arr+1指向的是arr[1]这个行数组。对其进行解引用,得到的是每一行数组的首地址,即*arr表示的是第0行数组的首地址,和arr[0]相等,*(arr+1)表示的是第1行数组的首地址,和arr[1]是相等的。假如要取第1行第2个元素的地址,就是arr[1]+2,因为此时arr[1]代表的是一维数组,所以它的元素就是一个数字,在加减的时候移动的就是元素的大小,例如+1就表示该数组中第1个元素,+3就表示数组中的3个元素(以0开始)。因为

    *(arr+1)和arr[1]相等,所以第1行第2个元素的地址也可以表示为*(arr+1)+2,对这个地址进行解引用,得到的就是数组元素的具体值,也就是*(*(arr+1)+2)。

    所以有如下公式,假如一个二维数组每行有N个元素,二维数组名是arr,那第i行第j个元素的地址是

    *(arr+i*N)+j,也可以表示为arr[i]+j。

    元素的值可以表示为*(*(arr+i)+j),或者可以表示为arr[i][j]。

    还用数组的形式来表示元素的地址和值,可以更方便编程人员的阅读,但是使用指针的方式更方便与C语言编译器阅读。

    验证代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int  main( void )
    {
         int  arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
         //分别使用不同的形式打印第2行,第3个元素的值和地址
         //根据推到出来的规律如下
         //该元素的地址
         printf ( "%p\n" ,*(arr+2*4)+3);
         printf ( "%p\n" ,arr[2]+3);
         printf ( "%p\n" ,&arr[2][3]);
         //该元素的值是12
         printf ( "%d\n" ,*(*(arr+2)+3));
         printf ( "%d\n" ,arr[2][3]);
         return  0;
    }

    执行结果如下

    0x7fff5fbff88c

    0x7fff5fbff82c

    0x7fff5fbff82c

    12

    12

            对上述二维数组arr,虽然arr[0]、arr都是数组首地址,但二者指向的对象不同,arr[0]是一维数组的名字,它指向的是arr[0]数组的首元素,对其进行“*”运算,得到的是一个数组元素值,即arr[0]数组首元素值,因此,*arr[0]与arr[0][0]是同一个值;而a是一个二维数组的名字,它指向的是它所属元素的首元素,它的每一个元素都是一个行数组,因此,它的指针移动单位是“行”,所以arr+i指向的是第i个行数组,即指向arr[i]。对arr进行“*”运算,得到的是一维数组arr[0]的首地址,即*arr与arr[0]是同一个值。当用int *p;定义指针p时,p的指向是一个int型数据,而不是一个地址,因此,用arr[0]对p赋值是正确的,而用arr对p赋值是错误的。


    四、数组指针

            既然不能将二位数组的数组名赋值给二位指针,那该用什么来表示二位数组呢。答案就是数组指针。数组指针就是指向数组的指针。

        int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

        int (*p)[4] = arr;

            如上图所示的声明方式,可以认为指针p就是指向数组的指针,这个数组中有4个int类型的元素,此时p的增量以它所指向的一维数组长度为单位。同时要想使用指针p来表示数组arr中的元素,上面总结的规律也是可以使用的。

    如下图的代码,就是将上面的arr换成了指针p,同样可以使用。

    int main(void)

    {

        int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

        int (*p)[4] = arr;

        //分别使用不同的形式打印第2行,第3个元素的值和地址

        //根据推到出来的规律如下

        //该元素的地址

        printf("%p\n",*(p+2*4)+3);

        printf("%p\n",p[2]+3);

        printf("%p\n",&p[2][3]);

        //该元素的值是12

        printf("%d\n",*(*(p+2)+3));

        printf("%d\n",p[2][3]);

        return 0;

    }

    使用数组指针指向一维数组

    int a[3]={1,2,3}; 那么p就是指向这个数组a的指针。
    int(*p)[3]=&a; // 这里赋值一定要用取地址符号。也就是取数组a的地址。

    不可以这样赋值: int(*p)[3]=a; // error :类型不兼容。a本来是数组类型,是不可以赋值给int(*)[3]这个类型的。

    但是这样是可以的int *p1=a; // ok 因为a可以隐式转换为int*类型,其值实际上就是数组第一个元素的地址,也就是&a[0]。


    数组指针练习题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    //打印数组
    void  print_Array( char  (*p)[30], int  *len)
    {
         for ( int  i=0;i<*len;i++)
         {
             printf ( "%s\n" ,p[i]);
         }
    }
     
    //数组排序
    int  sort( char  (*p)[30], int  *len)
    {
         int  ret = 0;
         char  tmp[100];
         if (p==NULL||len==NULL)
         {
             printf ( "function sort error" );
             ret = -1;
         }
         for ( int  i=0;i<*len;i++)
         {
             for ( int  j=i+1;j<*len;j++)
             {
                 if ( strcmp (p[i],p[j])>0)
                 {
                     strcpy (tmp,p[i]);
                     strcpy (p[i],p[j]);
                     strcpy (p[j],tmp);
                 }
             }
         }
         return  ret;
    }
     
    int  main( void )
    {
         char  array[10][30] = { "sdecs" , "codeq" , "owxja" , "qwer" , "bsdws" };
         int  count = 5;
         print_Array(array, &count);
         sort(array, &count);
         printf ( "排序之后的数组\n" );
         print_Array(array, &count);
         return  0;
    }

    执行结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    sdecs
    codeq
    owxja
    qwer
    bsdws
    排序之后的数组
    bsdws
    codeq
    owxja
    qwer
    sdecs

    上面的代码是使用数组指针做函数参数,接受主调函数传递过来的二维数组的地址,然后利用数组指针对二位数组进行相关的操作。



    五、指针数组

            说完了数组指针,现在接着要说一下指针数组,这两者并没有什么联系,放在一起是因为两者的声明比较像,有时候容易弄混,放在一起可以比较一下。

            指针数组就是数组里面存放的是指针这种数据类型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    int  main( void )
    {
         int  a = 1;
         int  b = 2;
         int  c = 3;
         int  *d = &a;
         int  *e = &b;
         int  *f = &c;
         int  *p[3] = { d, e, f };
         printf ( "%d\n" ,*p[0]);
         printf ( "%d\n" , *d);
         printf ( "%p\n" , p[0]);
         printf ( "%p\n" , &a);
         return  0;
    }

    执行结果

    1

    1

    0x7fff5fbff818

    0x7fff5fbff818

    如上图所示分别是指针数组的代码和相应的执行结果。

    上面的p就是一个数组,这个数组有3个元素,每个元素都是int *类型的,也就是每个元素都是指向int类型的指针。


    下面是指针数组的练习题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    //数组打印
    void  print_array( const  char  **p, const  int  *len)
    {
         for ( int  i=0;i<*len;i++)
         {
             printf ( "%s\n" ,p[i]);
         }
    }
     
    //元素排序
    int  sort( char  **p, int  *len)
    {
         char  **str = p;
         int  *count = len;
         char  *tmp = NULL;
         //函数返回值
         int  ret = 0;
         if (str==NULL||len==NULL)
         {
             printf ( "function sort error" );
             return  ret;
         }
         for ( int  i=0;i<*count;i++)
         {
             for ( int  j=i+1;j<*count;j++)
             {
                 if ( strcmp (str[i],str[j])>0)
                 {
                     tmp = str[i];
                     str[i] = str[j];
                     str[j] = tmp;
                 }
             }
         }
         return  ret;
    }
     
    int  main( void )
    {
         char  *array[] = { "sdjd" , "asdjf" , "peroa" , "asoeq" };
         int  count =  sizeof (array)/ sizeof (array[0]);
         //排序前打印
         print_array(array, &count);
         //调用排序函数
         sort(array, &count);
         //排序后打印
         printf ( "排序后打印\n" );
         print_array(array, &count);
         return  0;
    }

    执行结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    sdjd
    asdjf
    peroa
    asoeq
    排序后打印
    asdjf
    asoeq
    peroa
    sdjd

    在这里需要补充的一点是,C语言中没有字符串这种数据类型,字符串在C语言中使用字符数组来表示。

    注意点:①在调用函数的时候,使用了二级指针接受main函数中的指针数组,同时可以看到在传递数组个数的时候仍然使用了实参传递地址,形参使用指针来接受参数的这种形式,这是指针在做函数参数的时候非常重要的应用。

    在函数传递参数的时候,通过指针给主调函数中的变量间接复制,是指针存在最大的意义。例如想通过在被调函数中改变主调函数中变量的值,则可以在函数调用的时候将变量的地址传递过去,在被调函数中使用一级指针来接受,这样在被调函数中就可以通过指针来间接改变变量的值;同理,如果在被调函数中要改变主调函数中一级指针的值,则可以在被调函数中通过二级指针接受一级指针的地址,从而实现在被调函数中改变一级指针的值。同时这样做还有一个好处就是,因为被调函数只能有一个返回值,当想返回多个值的时候就很难实现,但是通过上面的那种方式,即在被调函数中通过地址来间接改变变量(指针也是一种变量)值的方式,就可以在被调函数中改变多个变量的值。而只是让函数返回函数执行状态的值,这样就可以判断出现了哪种情况。


    注意上面这段代码(1代码)和之前的数组指针练习题代码(2代码)的比较

    ①在计算数组元素个数的时候,2代码如果也使用和1代码相同的方式求元素个数,得到的结果永远都是10,但实际元素个数并不是10,出现这种现象的原因是因为2代码中固定了数组元素的个数,但是1代码中并没有固定。

    ②在排序交换数组元素的时候,使用的方式也不相同,1代码使用的是交换指针指向的方法,也就是说,指针中存储的数组的地址改变了,指针的指向变了;2代码使用的是交换交换数组的值,也就是指针指向不变,但是指针所指向的内存空间中的值变了。


    六、三级指针形参接受二级指针地址进行相关操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    //排序
    int  sort( char  ***p, int  *len)
    {
         char  *tmp = NULL;
         int  ret = 0;
         if (p==NULL||len==NULL)
         {
             printf ( "function sort error" );
             ret = -1;
         }
         
         for ( int  i=0;i<*len;i++)
         {
             for ( int  j=i+1;j<*len;j++)
             {
                 if ((*p)[i]<(*p)[j])
                 {
                     tmp = (*p)[i];
                     (*p)[i] = (*p)[j];
                     (*p)[j] = tmp;
                 }
             }
         }
         return  ret;
    }
    //给二级指针分配内存
    int  getMem( char  ***p, int  count)
    {
         int  ret = 0;
         if (p==NULL)
         {
             printf ( "function getMem error" );
             ret = -1;
         }
         *p = ( char  **) malloc ( sizeof ( char *)*(count));
         for ( int  i=0;i<count;i++)
         {
             (*p)[i] = ( char  *) malloc ( sizeof ( char )*100);
             sprintf ((*p)[i], "%d%d%d" ,i,i,i);
         }
         return  ret;
    }
    //打印数组
    void  printArray( char  ***p, int  count)
    {
         for ( int  i=0;i<count;i++)
         {
             printf ( "%s\n" ,(*p)[i]);
         }
    }
    //释放内存空间
    int  freePoint( char  ***p, int  count)
    {
         if (p==NULL)
         {
             return  -1;
         }
         for ( int  i=0;i<count;i++)
         {
             free ((*p)[i]);
         }
         free (*p);
         return  0;
    }
     
    int  main( void )
    {
         char  **p = NULL;
         int  count = 5;
         //分配内存
         getMem(&p, count);
         //打印数组
         printArray(&p, count);
         //排序
         sort(&p, &count);
         //打印数组
         printArray(&p, count);
         //释放内存
         freePoint(&p, count);
         return  0;
    }

    如上图所示的代码,在main方法中声明了一个二级指针,然后先讲二级指针的地址做实参传递给甘薯getMem,在函数getMem中使用三级指针做形参接受二级指针,在函数中分配相应的内存空间,然后赋值。

    代码注意点①在分配内存的时候,判断的是三级指针p是否为NULL,而不是二级指针

    ②在(*p)[i]的时候注意符号的优先级,上面的代码如果改成*p[i]就会出错,因为[]的优先级大于*,所以这样写会造成越界。

    展开全文
  • 二级指针的概念 首先任何值都有地址,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址,一级指针所关联...
  • c语言——结构体嵌套二级指针 如果一个结构体内嵌套二级指针二级指针,这里的students为二级指针,也对应了一对多的关系,一个老师,多个学生。 struct Teacher { char *name; char **students; }; 我们知道,...

    c语言——结构体嵌套二级指针

    如果一个结构体内嵌套二级指针了二级指针,这里的students为二级指针,也对应了一对多的关系,一个老师,多个学生。

    struct Teacher
    {
    	char *name;
    	char **students;
    };
    

    我们知道,二级指针指向一级指针的地址,三级指针指向二级指针的地址

    void test()
    {
    	
    	struct Teacher **teachers = NULL;
    
    	int ret = 0;
    	ret = allocateSpace(&teachers);
    	if (ret < 0)
    	{
    		printf("allocateSpace 函数调用出错!\n");
    		return;
    	}
    
    	//打印老师及其学生信息
    	printTeachers(teachers);
    
    	//释放内存
    	freeSpace(teachers);
    	teachers = NULL;
    
    }
    

    分配空间

    int allocateSpace(struct Teacher ***temp)
    {
    	if (NULL == temp)
    	{
    		//错误码 不同错误码表示不同错误
    		return -1;
    	}
    
    	struct Teacher **ts = malloc(sizeof(struct Teacher *) * 3);
    	for (int i = 0; i < 3; ++i)
    	{
    
    		//给老师结构体指针分配空间
    		ts[i] = malloc(sizeof(struct Teacher));
    
    		//给老师名字分配空间
    		ts[i]->name = malloc(sizeof(char) * 64);
    		sprintf(ts[i]->name, "Teacher_%d", i + 1);
    
    		//给学生指针分配内存
    		ts[i]->students = malloc(sizeof(char *)* 4);
    		for (int j = 0; j < 4; ++j)
    		{
    			ts[i]->students[j] = malloc(sizeof(char) * 64);
    			sprintf(ts[i]->students[j],"%s_Stu_%d",ts[i]->name,j + 1);
    
    		}
    
    	}
    
    	*temp = ts;
    
    	return 0;
    }
    

    打印与释放

    打印

    void printTeachers(struct Teacher **teachers)
    {
    	if (NULL == teachers)
    	{
    		return;
    	}
    
    	for (int i = 0; i < 3; ++i)
    	{
    		printf("%s\n", teachers[i]->name);
    		for (int j = 0; j < 4; ++j)
    		{
    			printf("   %s\n",teachers[i]->students[j]);
    		}
    	}
    }
    
    

    释放

    
    
    void freeSpace(struct Teacher **teachers)
    {
    	if (NULL == teachers)
    	{
    		return; 
    	}
    
    	for (int i = 0; i < 3; ++i)
    	{
    
    		if (teachers[i] == NULL)
    		{
    			continue;
    		}
    
    		if (teachers[i]->name != NULL)
    		{
    			free(teachers[i]->name);
    			teachers[i]->name = NULL;
    		}
    
    		for (int j = 0; j < 4; ++j)
    		{
    			if (teachers[i]->students[j] != NULL)
    			{
    				free(teachers[i]->students[j]);
    				teachers[i]->students[j] = NULL;
    			}
    		}
    
    		free(teachers[i]->students);
    		teachers[i]->students = NULL;
    
    
    		free(teachers[i]);
    		teachers[i] = NULL;
    	}
    
    	free(teachers);
    	teachers = NULL;
    }
    

    运行

    Teacher_1
       Teacher_1_Stu_1
       Teacher_1_Stu_2
       Teacher_1_Stu_3
       Teacher_1_Stu_4
    Teacher_2
       Teacher_2_Stu_1
       Teacher_2_Stu_2
       Teacher_2_Stu_3
       Teacher_2_Stu_4
    Teacher_3
       Teacher_3_Stu_1
       Teacher_3_Stu_2
       Teacher_3_Stu_3
       Teacher_3_Stu_4
    
    展开全文
  • int (*p[num])( char*,int,int );...然后今天主要理一下函数指针数组和二级指针。 函数指针数组 函数指针数组中,存放的一定要是相同返回值类型,以及相同参数列表的函数指针,这样数组可...
    int (*p[num])( char*,int,int );
    
    int (*(*p)[num])(int a); 

    上一篇博客最后的两个例子的答案分别是:函数指针数组,函数指针数组的指针。

    函数指针数组指针和前面的数组指针其实没有太大区别。然后今天主要理一下函数指针数组和二级指针。

     

    函数指针数组

    函数指针数组中,存放的一定要是相同返回值类型,以及相同参数列表的函数指针,这样数组可以通过下标来调用不同的函数,省去了使用大量的判断语句。下面举个例子:

    假设你要看电影,下面有4种类型的,动作,浪漫,卡通,搞笑,然后再输入电影名观看。按照以前我可能就会是一堆if else或者switch case来判断 ,但现在可以这样:

    #include<stdio.h>
    
    void watch_action(char* name)
    {
    	printf("Action movie  <%s> starts\n",name);
    }
    
    void watch_funny(char* name)
    {
    	printf("Funny movie  <%s> starts\n",name);
    }
    
    void watch_romantic(char* name)
    {
    	printf("Romantic movie <%s> starts\n",name);
    }
    
    void watch_cartoon(char* name)
    {
    	printf("cartoon <%s> starts\n",name);
    }
    
    int main(int argc, char const *argv[])
    {
    	void (*watch[4])(char* name)={watch_action,watch_funny,watch_romantic,watch_cartoon};
    	printf("what kinds of movie would you want\n");
    	int num;
    	scanf("%d",&num);
    	printf("please input the movie name of this kinds\n");
    	char movie_name[128];
    	scanf("%s",movie_name);
    	watch[num](movie_name);
    	return 0;
    }

     通过num来调用不同的函数,省去了一堆判断语句,感觉还是方便蛮多的。

     

     

    二级指针:

            在指针的定义时就说过,指针变量虽然保存的是别人的地址,但其本身也是有地址的。而指向指针地址的指针,就叫做二级指针。

    那啥时候会用到二级指针?不急,先看下面代码:

    #include <stdio.h>
    
    int change_1(int b)
    {
    	b = 10;
    	return b;	
    }
    
    int change_2(int *p)
    {
    	*p = 15;
    }
    int main(int argc, char const *argv[])
    {
    	int a = 5;
    	change_1(a);
    	printf("%d\n",a);
    	change_2(&a);
    	printf("%d\n",a);
    	return 0;
    }

    你觉得输出是多少 ?  编译后结果是 5和15 也就是说change_1()这个函数没有把a修改了。C语言中函数的传参是值传递,change_1()只不过是把实参a的值5传给了局部变量b,然后b在被赋值10并返回,函数结束, b的生命周期也结束了。而主函数中的a根本就没有发生变化。要修改a的值,就要用第二种方法,前面我们说了,指针指向的是地址, change_2()中p得到的是a所在的地址,而*p就代表这个地址中的内容,我们对*p进行修改,就代表我们对这个地址上的变量即 a进行了修改。

    所以,想要修改一个数据的值,就要找到他的地址,用一级指针来修改。以此类推, 想要修改指针的值,我们就要找到指针的地址,用二级指针来对他进行修改。

    下面可以看下这个代码的结果,可能会更清晰一点:

    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
    	int a =5;
    	int* p;
    	p = &a;
    	int** pp;
    	pp = &p;
    	printf("&a:%p\n",&a);
    	printf("&p:%p\n",&p);
    	printf("p:%p\n",p);
    	printf("&pp:%p\n",&pp);
    	printf("pp:%p\n",pp);
    	printf("*pp:%p\n",*pp);
    	printf("&(*pp):%p\n",&(*pp));
    	return 0;
    }

    取这些变量的地址,地址运算符“&”,运算操作是取地址。编译结果:

    画个图:

    可以很清楚的看到  a的地址被放入了一级指针p当中 p的地址被放入了二级指针pp当中  

     p == &a 说明 *p == a       pp == &p 说明*pp == p     *pp == &a 说明 **pp == a  

    也就是 **pp == *p == a  

    最后举个具体用例吧。

    #include <stdio.h>
    int main(int argc, char const *argv[])
    {
    	char* num[9]={"one","two","three","four","five","six","seven","eight","nine"};
    	char** p;
    	p = &num[0];
    	int number;
    	scanf("%d",&number);
    	printf("English Number is %s\n",*(p+number-1));
    	return 0;
    }

    定义一个指针数组num,输入阿拉伯数字转换成英文数字。这里如果单单只有一级指针是不够的,一级指针只能找到字符串所在的位置,但是找不到其首地址,导致无法输出。所以需要二级指针二级寻址来输出。

    展开全文
  • 主要介绍了详解C语言-二级指针三种内存模型的相关知识,文中代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
  • 指针:C语言二级指针与二维数组

    千次阅读 2019-04-09 21:25:59
      最近用C语言写LeetCode 有的题目给的函数把二维数组用二级指针传进来 并传入行数和列数 引起一些疑惑 本来以为C语言学得海星,查了一些资料后,觉得自己还是个弟弟 : ( 按一维数组的思路处理二维数组,将二维...
  • 摘自:《C语言入门》 http://c.biancheng.net/c/ ...如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的...
  • c语言二级指针与指针数组

    千次阅读 2019-05-19 18:38:05
    一、代码 int main(int argc, const char * argv[]) { int a[] = {1,2,3}; int b[] = {4,5,6}; int c[] = {7,8,8}; int* arr[] = {a,b,c}; int** p = arr;...、运行结果 三、内存图解
  • c语言二级指针

    千次阅读 2018-12-13 09:51:41
    二级指针做输入_第1种内存模型 直接利用二级指针 首先看指针数组(变量为指针) 也就是数组中存的都是地址 #include&lt;stdio.h&gt; void main() { int i = 0, j = 0; int num = 0; char *myArray[] ...
  • 二级水平的指针个人理解与解释 有个人的代码解释与验证 纯属个人理解!
  • 总结:其实链表使用二级指针的好处就是,不管是头插尾插等操作后,链表的根节点地址不需要改变。如果链表是全局变量,那么就不用操作链表后返回该链表的根节点地址。直接访问全局的根节点地址就可以访问整个链表。 ...
  • 很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是“指针”: 在执行C程序的时候,由于我们的数据是存储在内存中的。所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的...
  • 关于C语言二级指针正确使用总结 什么是二级指针 C语言中的二级指针其实就是指向指针的指针,指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。同理可以构建三级或者N级指针,但是一般情况下用不到多级...
  • C语言学习—一级指针、二级指针的类型转换的进阶理解 类型转换都会在编程的时候运用到,很多人可能直观理解类型转换就是转换成另一个类型。其实这样理解也没有错,但是面对下面这种情况,就会出现段错误了: int ...
  • c语言里面二级指针可以被一级指针替代吗?一 、 结论二、环境三、代码块四 、结构理解 一 、 结论 不可替代,存在即合理 二级指针理解: 指向指针的指针 二、环境 win10 MinGW64 三、代码块 #include <stdio.h&...
  • c语言二级指针与二维数组

    千次阅读 2019-05-20 15:00:56
    一、二维数组的地址不能赋给二级指针的原因 int arr[][3] = { { 1,2,3 },{ 4,5,6 },{ 7,8,9 } }; int** p = arr; 二、指针遍历二维数组 int* p1 = arr; for (int i = 0; i < sizeof(arr)/sizeof(arr[0][0]); ...
  • 什么是指针? 在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。...
  • int *p=(int)(p):表示p为二级指针,指向一个int型的指针数据,也就是p指向一个整形指针。 假设有int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量 这种关系转换成C语言代码为: int a =100...
  • c语言实现单链表 二级指针在单链表的使用

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,313
精华内容 27,325
关键字:

二级指针c语言

c语言 订阅