虽然工作多年,数组的相关知识总是遗忘,不能随心所欲的使用,特别是数组名的含义以及使用数组名解引用数组成员,尤其是二维数组,相关的知识点总是很久才能捋顺,现在做个记录,即使自己遗忘了,也能快速理解这部分知识。希望能给需要的人一些帮助。
回归正题,分别说一下一维数组和二维数组。
一,一维数组:
char a[5]={1,2,3,4,5};
一维数组的数组名a是表示首元素的地址,这个非常重要。
1 | 2 | 3 | 4 | 5 |
0xa000 | 0xa001 | 0xa002 | 0xa003 | 0xa004 |
上面的表示的是内存中的数据,下面是内存的地址。a的值就是0xa000,其实c语言设计数组的初心就是开辟连续的空间来存储数据,由于空间是连续的,所以只需要知道开辟空间的起始地址就可以了,故a就是这个作用。对于数组成员的访问非常简单就是a[i],另外一个就是*(a+i),这个也非常容易理解,说白了就是指针的解引用,a是首元素的地址 a+i就是第i个元素的地址。
到了这里你以为你掌握了一维数组了?那我让你使用数组指针遍历数组成员,你可以吗?
何为数组指针?指针数组又是什么?数组指针的本质是指针,而这个指针是指向数组的,指针数组的本质是数组,数组的成员是指针。定义如下:
指针数组 :char *arry[5];// 优先级[] > * 所以arry先和[]结合,是个数组,数组的成员是char * ,其实和char arry[5] 定义方式一样,只是数组内存的内容不同而已。
数组指针:char (*p)[5]; 为啥要加上(),如果不加就是上面的指针数组,加上()之后就是指针,指向数组。
很明显如果用来遍历数组中的成员,肯定用数组指针,但是如何使用呢?
数组指针指向的是数组,肯定要把数组的地址给这个指针,而不是数组首元素的地址。这就涉及到a和&a的区别。
a是数组名,为首元素的地址,即&a[0]. a++指向下一个数组元素,即a[1].
&a是获取数组的地址,(&a)++指向下一个数组的位置,需要跨越一个数组,也就是a[5]的位置(非严谨说法)
综上a和&a的步长是不相同的,虽然他们的值是相同的,这个也好理解,数组的地址就是和首元素的地址是一样的。下面的代码就很好理解了:
char a[5]={1,2,3,4,5};
char (*p)[5]=NULL;
p=&a;
如何使用p遍历数组元素呢?
根据 p = &a,所以*p 就是a,根据a遍历数组元素就很容易了,可以使用a[i],也可以*(a+i),
结合起来就是 *(*p+i)
int i;
for(i=0;i<5;i++)
{
printf("%d ",*(*p+i));//遍历输出数组的值
}
以上基本掌握了一维数组和数组指针相关的内容基本掌握,下面介绍二维数组。二维数组理解起来是有一些难度的,每次彻底想通,都需要花费一些时间。
首先二维数组的本质是多个一维数组,也是连续的内存。
int a[3][2] = {1,2,3,4,5,6}, 平常说法就是3行2列的数组,因为内存其实线性连续的,数组成员的地址是连续的,只是为了访问方便写成二维数组,其本质就是3个一维数组,分别是a[0], a[1], a[2],每个一维数组都有两个成员。
可以结合上面的图理解二维数组,int a[3][2]其实是3个一维数组,这个三个数组的名字分别是a[0],a[1],a[2].其本质是int *,也就是a[0],a[1],a[2]分别保存三个一维数组的首元素的地址。访问第i个数组的第一个元素就是*(a[i]),第i个数组的j个数据就是*(a[i]+j).又因为a[i] 等价于*(a+i),带入后为
*(*(a+i)+j)
如果还是不好理解,结合一维数组,int arry[2] = {1,2}, 上面的a[0]相当于arry,类型为int *,保留首元素的地址。又因为a指向a[0],a[1],a[2]为元素的数组,即a指向的其实是3个数组的第一个数组,a+1指向的就是第二个数组,也就是a是一个行指针,跨越的是整个一维数组,所以a的本质是数组指针,指向的是第一个一维数组的地址。
int a[3][2] = {1,2,3,4,5,6};
int (*p)[2] = NULL;
p = a;
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<2;j++)
{
printf("%d ",*(*(p+i)+j));//遍历输出
}
}
以上为二维数组使用数组指针进行遍历的相关内容