二维数组与指针复习

请注意,本文编写于 131 天前,最后修改于 130 天前,其中某些信息可能已经过时。

最近在练习C语言计算机二级的程序设计题,碰到了二维数组和指针的结合,当时怎么调试都不对,自己也记不清楚该怎么用了就跑去看书翻资料重新复习。
本次复习看的讲解:点击访问

自己纠结的问题是二维数组 int a[3][4]的数组名是二级指针吗?

答案不是,而在上面的复习讲解上说是地址的地址是错的(但是他的讲解确实很让人懂二维数组的使用),
a退化为指针后,类型为int (*)[4],该指针指向含4个int类型元素的一维数组。
(例:一维数组b[4],b则退化为元素指针)
既然a都不是指针的指针,则想通过int **p=a对p进行赋值就是不可实现的。

那么如何实现通过指针p来对a[3][4]来进行操作?

在看如何赋值之前有必要了解一下

这几个&a,a,a[0],&a[0],&a[0][0]地址(因a[0][0]为元素值,不在讨论范围内)的不同之处。

#include<stdio.h>
void main()
{
    int a[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
    printf("&a=%d\n",&a);
    printf("&a+1=%d\n",&a+1);
    printf("a=%d\n",a);
    printf("a+1=%d\n",a+1);
    printf("&a[0]=%d\n",&a[0]);
    printf("&a[0]+1%d\n",&a[0]+1);
    printf("a[0]=%d\n",a[0]);
    printf("a[0]+1=%d\n",a[0]+1);
    printf("&a[0][0]=%d\n",&a[0][0]);
    printf("&a[0][0]+1=%d\n",&a[0][0]+1);
}

运行结果(该结果为本人电脑运行看,可能有所不同):

&a=5241364
&a+1=5241412
a=5241364
a+1=5241380
&a[0]=5241364
&a[0]+15241380
a[0]=5241364
a[0]+1=5241368
&a[0][0]=5241364
&a[0][0]+1=5241368

通过观察可以看出&a,a,a[0],&a[0],&a[0][0]的结果都是5241364,证明他们的地址是相同的。但是都进行+1操作后就知道不同了。
&a+1和&a差值为48,正好是二维数组的长度(4(int长度)X3X4=48),+1是加了一个二维数组长度。
a+1和a的差值为16,是a[][4]的长度,进行+1则从a退化为a[0]的地址进行加值之后变为a[1]的地址,可以证明a加1是从a[0]到a[1]的变化。
&a[0]+1和&a[0]的差值为16,&a[0]表示一行(一个一维数组)的首地址,进行+1后是下一组的首地址&a[1]。
a[0]+1和a[0]的差值为4,a[0]表示这一行的首元素的地址,+1则是从a[0]开始退化为a[0][0]的指针之后进行加值则变为a[0][1]的地址;
&a[0][0]+1和&a[0][0]的差值为4,&a[0][0]表示这一行(一维数组)的首元素的值的地址,当+1则变为a[0][1]的地址。
如果还是不了解看下图(该图片来自于点击访问源地址

分析图
分析图

由上面了解之后再看下面就方便理解了。

第一种方式:通过将定义p为:int (*p)[4]形式,和上面a所退化为指针后的类型相同,因此则可以直接将a赋值给p;
代码如下:

#include<stdio.h>
void main()
{
    int a[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
    int (*p1)[4]=a;
    
    for(i=0;i<3;i++)//数组形式(方便理解)
    {
        for(j=0;j<4;j++)
        printf("%3d ",p1[i][j]);
        printf("\n");
    }
    printf("\n");
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++)//指针形式
        printf("%3d ",*(*(p1+i)+j));
        printf("\n");
    }
}

第二种方式:在内存中,并不存在多维数组,因为内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的。(摘自讲解中的话),因此我们只要找到令指针指向二维数组的首地址就能通过顺序来找到接下的元素。因为二维数组a的地址和a[0]是一样的,我们让int *p=a[0],则可以找到首地址,调用过程中需要通过*(p1+4*i+j)来找接下来的元素。

#include<stdio.h>
void main()
{
    int aa[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
    int *p1=a[0];//[0]是地址
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++)//
        printf("%3d ",*(p1+4*i+j));
        printf("\n");
    }
}

到此复习完毕!

添加新评论

已有 2 条评论

我上网查才知道tql啥意思