我所理解的二维数组

来源:互联网 发布:mac如何安装阿里旺旺 编辑:程序博客网 时间:2024/05/16 23:33

要对二维数组做一些详细的理解,那么我们先要复习下一维数组的几点知识:

对于一维数组,大家肯定知道,一维数组的数组名可以当成一维指针使用,也就是说,可以用一个一维指针,把数组首地址赋值给这个指针,然后把这个指针当成数组名用.

int arr[5]={1,2,3,4,5};//一维数组

int *p=arr;

然后可以用指针p来处理这个数组里面的元素,比如说p[0]就是arr[0],p[1]就是arr[1],和数组名的使用都完全一样.

对于一维数组,*(arr+i)等价于arr[i],可以推出一个特例,*arr等价arr[0];

以上的结论在二维数组中同样适用,,但是要做一些小小的变形,首先我们定义一个足够大的二维数组,避免下面的讨论中出现越界问题,就像这样:

int array[M][N];//定义一个M*N的二维数组 M和N都是一个很大的整数

二维数组中,我们一般用行和列来区分,M*N就是一个M行N列的数组.

对于二维数组而言,里面的元素可以用下标来表示,比如说array[i][j]

二维数组的下标也是从0开始,array[0][0]就是数组的第一个元素

二维数组比一维数组而言更加的复杂,上面说过, 对于一维数组,*(arr+i)等价于arr[i],那么对于二维数组来说,array[i][j]可以有如下表示方法:

array[i][j] (*(array+i))[j] *(array[i]+j) *(*(array+i)+j)

其中i和j都是可以取0的,也就是说如果i或j等于0,会有如下几种方式

i等于0的情况(写法1)

array[0][j] (*array)[j] *(array[0]+j) *(*array+j)

j等于0的情况(写法2)

array[i][0] (*(array+i))[0] *array[i] **(array+i)

上面的括号都是因为优先级的原因,去掉的话结果就不一样了,其中优先级有

小括号()>中括号[]>取值符号*>加号+

对于一个二维数组,我们可以从几个不同的方向来分析

方向一:数组

数组都是存放在一块连续的内存中的,也就是说可以用一个一维指针指向其中一个元素

比如说int *p1=&array[0][0];//这里等价int *p1=arr[0];

然后想要访问array[i][j],就是*(p1+i*N+j)或者*(p1+j*M+i),这个可以应用到各种地方,比如说想要用一维数组来代替二维数组使用,就可以用上面这种方式;

通过上面的赋值之后p1其实就可以当做array[0]使用,也就是说*(p1+i*N+j)等价*(array[0]+i*N+j),由上面写法1得到另外一个等价的形式array[0][i*N+j]

假设有m和n和元素array[m][n],m和n可以为正数或负数,m可以大于M,n也可以大于N,它等价array[0][m*N+n],也就是说如果满足0<=m*N+n<=M*N-1,那么这个元素就存在于这个数组当中.转换为标准的下标就是i=(m*N+n)/N,j=(m*N+n)%N

二维数组无论是传参数还是申请内存都要事先指定数组的列的大小,一维数组则不需要,也就是说如果你想要一个x*y大小的二维数组,但是xy的值不是常量的话,可以用申请一维数组,然后用上面的方式当二维数组使用.

方向二:数组的数组

二维数组可以看成数组的数组,因为array[0]可以视为一个一维数组的数组名,array[0][0]是array[0]中的第一个元素,array可以看成一个数组的数组名,也就是看成一个常属性的数组指针.

int (*q)[N];//定义一个数组指针,要指明数组的列

q=array;//这样的话就可以用q来代替array,用法是一样的

如果是申请一个数组指针,那么除了q=array之外,还可以有q=&array[0]这样,他们的效果是一样的.区别于array,q是一个指针,所以q可以进行q++这样的操作,但是需要注意的是,q++之后,q不再指向首地址,虽然可以q[i][j]但是和array[i][j]已经不是同一个元素了

#include<stdio.h>

int main()

{

int array[3][4]={0};

int (*q)[4]=array;

q++;

q[1][2]=4;

printf(“array[1][2]=%d array[2][2]=%d ”,array[1][2],array[2][2]);

getchar();

return 0;}

对于数组指针,q++等于移动了一个数组长度的地址,上面的代码可以说明,你也可以试着把所有内容全部打印出来.

最后补充下关于二维数组元素地址的问题,用scanf的话需要取地址,我们首先看下关于二维数组的元素

array[i][j] (*(array+i))[j] *(array[i]+j) *(*(array+i)+j)

取地址加一个取地址符&就可以,取值符号和取地址符号相当于逆运算,也就是说可以写成下面四种方式代表array[i][j]的地址:

&arr[i][j] &(*(array+i))[j] array[i]+j *(array+i)+j

scanf(“%d”,array[i]+j);//四种方式都可以使用

附录1.字符串数组和字符指针数组

字符串数组也就是char类型的二维数组,使用方式和上面的类似,只是需要注意下字符串后面的’’就可以了.

字符指针数组,一般用来在堆区存放字符串用的,数组元素是指针,这些指针放在一块相邻的区域,但是指向的内容不一定在相邻的区域

char *p[5];

for(int i=0;i<5;i++)

{

p[i]=(char *)malloc(sizeof(char)*i);//指针数组每个p[i]指向的内存大小可以不同

}

//然后可以p[3][2]这样使用,但是不代表p是二维数组