• 2022/11/21[指针] 多维数组与指针的联系


    1、指向数组元素的指针变量

    1. #include<stdio.h>
    2. int main()
    3. {
    4. int* p;
    5. int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
    6. int i, j;
    7. //将第0行第0列的地址赋给p
    8. for (p = a[0]; p < a[0] + 12; p++)//注意是a[0]
    9. {
    10. if ((p - a[0]) % 4 == 0)
    11. printf("\n");
    12. printf("%-4d", *p);
    13. }
    14. printf("\n");
    15. return 0;
    16. }

    上述是由int*实现的,现在我们可以使p指向的不是整型变量,而是指向包含m个元素的一维数组,这时,如果p先指向a[0],那么p+1就不是指向a[0][1],而是指向a[1],p的增长以一维数组的长度为单位。 

     2、指向由m个元素组成的一维数组的指针变量

    数据类型:(*p)[m]

    功能:指定变量p是一个指针变量,它指向包含m个元素的一维数组

    例如:int(*p)[4];

               p=a;

    p指向a数组,p++的值为a+1,只能对行进行操作,不能对行中的某个元素进行操作,只有执行*(a++)将行转列后,才能对数组元素进行操作

    程序:输出二维数组任意一行任意一列元素的值

    1. #include<stdio.h>
    2. int main()
    3. {
    4. int a[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
    5. int(*p)[4];//p指向包含4个整型的一位数组
    6. int i, j;
    7. p = a;//将二维数组首地址赋给p
    8. scanf_s("%d%d", &i, &j);
    9. printf("a[%d][%d]=%d", i, j, *( * (p + i) + j));
    10. return 0;
    11. }

    注意,此时p已经指向了一维数组,因此(p+i)指向的是a[i],*(p+i)就是a[i][0]的地址,加上j就是a[i][j]的地址 

    分析:指针变量p指向包含4个整形的一维数组,p+i表示第i行首地址,在二维数组中,*(p+i)表示第i行第0列的元素的地址,即p[i],此时将行指针转化为列指针,则*(p+i)+j 表示第i行第j列元素的地址,即p[i]+j,而*(*(p+i)+j)代表第i行第j列元素的值

    如果对一维数组使用此类型会有怎样的结果?分析以下程序:

    1. #include<stdio.h>
    2. int main()
    3. {
    4. int a[4] = { 1,3,5,7 };
    5. int(*p)[4];
    6. p = &a;
    7. printf("%d\n", (*p)[3]);
    8. return 0;
    9. }

    输出结果为a[3]即7.

    注意第6行不应写成“p=a;”,因为这样写表示p的值是&a[0],指向首元素a[0].“p=&a;”表示 p指向一维数组(行),(* p)[3]是p所指向的行中序号为3的元素。

            总结:要注意指针变量的类型,从“int( * p)[4];”可以看到,p的类型不是int *型,而是int( *)[4]型,p被定义为指向一维整型数组的指针变量,一维数组有4个元素,因此p的基类型是一维数组,其长度是16字节。

            “*(p+2)+3”括号中的2是以p的基类型(一维整型数组)的长度为单位的,即p每加1,地址就增加16个字节(4个元素,每个元素4个字节),而“*(p+2)+3”括号外的数字3,不是以p的基类型的长度为单位的。由于经过*(p十2)的运算,得到a[2],即&a[2][0],它已经转化为指向列元素的指针了,因此加3是以元素的长度为单位的,加3就是加(3×4)个字节。虽然 p+2和*(p+2)具有相同的值,但由于它们所指向的对象的长度不同,因此(p+2)+3和*(p+2)+3的值就不相同了。

    3.用指向数组的指针作函数参数

    一维数组名可以作为函数参数,多维数组名也可作函数参数。用指针变量作形参,以接受实参数组名传递来的地址。可以有两种方法:①用指向变量的指针变量﹔②用指向一维数组的指针变量。

    程序:有一个班,3个学生,各学4门课,计算总平均分数以及第n个学生的成绩。

    1. #include<stdio.h>
    2. int main()
    3. {
    4. void ave(float* p, int m);
    5. void search(float(*p)[4], int n);
    6. float score[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
    7. int n;
    8. //这里的ave求元素不能用二维数组名,使用*将行形式变成列形式即&score[0][0]
    9. ave(*score, 12);//因为要求元素
    10. printf("enter 0~2:\n");
    11. scanf_s("%d", &n);
    12. search(score, n);//我要的形参就是行形式,直接写二维数组起始名
    13. return 0;
    14. }
    15. void ave(float* p, int m)
    16. {
    17. float sum=0, aver=0;
    18. //此时实参传递给p为&score[0][0],又变成了指针在一维数组中的应用
    19. float* b = p + m;
    20. for (; p < b; p++)
    21. {
    22. sum += *p;//在已经求了地址的基础上再求值
    23. }
    24. aver = sum / m;
    25. printf("the average is %f\n", aver);
    26. }
    27. void search(float(*p)[4], int n)
    28. {
    29. int i;
    30. for (i = 0; i < 4; i++)
    31. printf("%6.2f", *(*(p + n) + i));
    32. printf("\n");
    33. }

    解析:在ave函数中定义为float*p,实参写为*score,即表示为score[0],也即&score[0][0],指针转换成了列形式,这样就可以利用程序先后指向数组中的每一个元素。

            在search函数中定义为float(*p)[4],指向的不是单个元素,而是 带有4个整型的一维数组,注意,实参此时应该是二维数组名,因为我要的就是行形式,这样*(p+n)就表示&a[n],*(p+n)+i就表示&a[n][i]了

  • 相关阅读:
    能源路由器入门必读:面向能源互联网的架构和功能
    滑动窗口问题
    Dubbo 路由及负载均衡性能优化
    Flux脚本语言基础使用-查询数据(InFluxDB 查询语言)
    第2章 第一个Spring Boot项目
    STM32:DMA数据转运+AD多通道(软件篇)
    NC 添加IRule 后置前置规则
    python实例练习00001:打开文件输出文件内容
    看动画,学Java基础教程13:变量
    Oracle Primavera Unifier 23.6 新特征
  • 原文地址:https://blog.csdn.net/fangzelin5/article/details/127970819