• 数组指针/指针数组和一/二级指针


    数组指针和指针数组

    二级指针的作用详解

    首先确定优先级:()>[]>*,另外数组指针,类比整型指针,表示指向数组的指针;指针数组,类比整型数组,表示元素为指针的数组。

    数组指针

    int (*p)[n] 首先()优先级高,它是一个指针,指向一个整型数组。n为数组的长度,当p+1时需要跨越n个整型数据的长度,通常用来表示二维数组及二维数组的函数传参。

    一维数组赋值给数组指针时,需要取数组地址或对其进行强制转换,另外相当于二维数组中只有一个行元素,p3+1的地址没有意义,*(p3+1)也无法显示。

    1 char a[5] = { 'A', 'B', 'C', 'D' };
    2 char(*p3)[5] = &a;
    3 char(*p4)[5] = (char (*)[5])a;

     二维数组赋值给数组指针时,具体间接访问格式,可以参考上一篇博文指针和数组的关系

     1 # include <stdio.h>
     2 int main(void)
     3 {
     4     int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
     5     int i, j;
     6     int (*p)[4] = a;  //记住这种定义格式
     7     for (i=0; i<3; ++i)
     8     {
     9         for (j=0; j<4; ++j)
    10         {
    11             printf("%-2dx20", *(*(p+i)+j));  /*%-2d中, '-'表示左对齐, 如果不写'-'则默认表示右对齐;2表示这个元素输出时占两个空格的空间*/
    12         }
    13         printf("
    ");
    14     }
    15     return 0;
    16 }

    二维数组元素地址赋值给一维指针,对元素进行访问时需要跨越n个整型数据的长度,即p + i*N +j == &a[i][j]

     1 # include <stdio.h>
     2 int main(void)
     3 {
     4     int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
     5     int i, j;
     6     int *p = &a[0][0];  //把a[0][0]的地址赋给指针变量p
     7     for (i=0; i<3; ++i)
     8     {
     9         for (j=0; j<4; ++j)
    10         {
    11             printf("%-2dx20", *(p+i*4+j));
    12         }
    13         printf("
    ");
    14     }
    15     return 0;
    16 }

    指针数组

     int *p[n] 首先[]优先级高,它是一个数组,前面为int*,表示数组的元素为整型指针,也可表示为int **p, 这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量,可以用来存放变量地址。

    其中C中处理字符串和链表数据结构中用该数据类型较多,涉及到二级指针时也容易出问题。

     1 int a = 1;
     2 int b = 2;
     3 int *p[2];
     4 p[0] = &a;
     5 p[1] = &b;
     6 
     7 printf("%p
    ", p[0]); //a的地址
     8 printf("%p
    ", &a); //a的地址
     9 printf("%p
    ", p[1]); //b的地址
    10 printf("%p
    ", &b); //b的地址
    11 printf("%d
    ", *p[0]); //p[0]表示a的地址,则*p[0]表示a的值
    12 printf("%d
    ", *p[1]); //p[1]表示b的地址,则*p[1]表示b的值
    13 
    14 
    15 //将二维数组赋给指针数组
    16 int *pp[3]; //一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2],所以要分别赋值
    17 int c[3][4];
    18 for (int i = 0; i < 3; i++)
    19     pp[i] = c[i];

    数组指针是一个指针变量,占有内存中一个指针的存储空间;

    指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。

    指向二维数组时,指针数组和数组指针访问数组元素时完全相同,但函数传参时,只能用数组指针,原因参见指针和数组的关系

    int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } }; //2行3列的二维整型数组
    int(*p)[3]; //数组指针,指向含有3个元素的一维数组
    int *q[2]; //指针数组,一个数组内存放2个指针变量
    
    p = a;
    q[0] = a[0];
    q[1] = a[1];
    
    //输出第1行第2列的值
    printf("%d
    ", a[1][2]); //5
    
    printf("%d
    ", *(p[1] + 2)); //5
    printf("%d
    ", *(*(p + 1) + 2)); //5
    printf("%d
    ", (*(p + 1))[2]); //5
    printf("%d
    ", p[1][2]); //5
    
    printf("%d
    ", *(q[1] + 2)); //5
    printf("%d
    ", *(*(q + 1) + 2)); //5
    printf("%d
    ", (*(q + 1))[2]); //5
    printf("%d
    ", q[1][2]); //5

    一级指针和二级指针

     在进行函数指针传参时,编译器总是要为函数的每个参数制作临时副本(即形参为实参的副本),在调用的时候,实参和形参是不同的内存空间,只是,这个内存空间存放的指针指向的是同一块地址 ,所以形参在函数执行中可以访问实参指向的内存空间,但是形参的指向的改变(即形参所指向的内存空间与实参不同)并不能影响实参,但改变形参所指向的空间的值时(改变形参指向的内存空间的值),实参指向会改变。

    一级指针的作用:在函数外部定义一个值m,在函数内对m进行赋值改变,函数结束后对值m生效。一级指针不管形参、实参都指向值m的地址,对一级指针进行解引用时都是访问m的地址空间,然后访问m,因此若改变形参指向的空间的值(即改变了m的值),则实参也会改变。

    二级指针作用:在函数外部定义一个指针p,在函数内给指针赋值,函数结束后对指针p生效。二级指针不管形参、实参都指向指针p,对二级指针进行解引用时都是先访问指针p的地址空间,再访问指针p,因此若改变形参指向的空间的值(即改变了指针p的值),则实参也会改变。

    如果用了二级指针,但不想改变外部的指针p,可以在函数内部对二级指针指向的空间的值做一个拷贝。

     1 void  my_malloc(char **s)  
     2 {  
     3     *s=(char*)malloc(100);  
     4 }  
     5  
     6 void  main()  
     7 {  
     8     char  *p=NULL;  
     9     my_malloc(&p);
    10     //do something
    11     if(p)
    12         free(p);  
    13 }  

    这里给指针p分配内存,do something,然后free(p),如果用一级指针,那么就相当于给一个p的拷贝s分配内存,p依然没分配内存,用二级指针之后,才对p分配了内存。

    应用上面的二级指针的例子

     1 void getstring_(char **p){
     2     //char *p;
     3     *p = malloc(100);
     4     memset(*p, 0, 100);
     5     strcpy(*p, "hello");
     6 }
     7 
     8 void test_(){
     9     char *ret = NULL;
    10     getstring_(&ret);
    11     printf("%s
    ", ret);
    12 }
    13 
    14 int main(){
    15     test_();
    16 
    17     system("pause");
    18     return 0;
    19 }
  • 相关阅读:
    shell script数组使用函数输出
    Yii2文件上传
    ubuntu 安装遇到黑屏
    使用函数
    ionCube 安装
    记录LNMP环境彻底删除绑定域名及网站文件夹/文件的过程
    lnmp环境 开启pathinfo
    国外知名设计教程网址收集
    26个国外在线教育网站
    前端学习网站汇总
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/10116416.html
Copyright © 2020-2023  润新知