作为一个普通的大一新生,深感被指针支配的恐惧,在看过一些文章后对数组指针有了一点自己的见解,如有不完整,错误,也希望得到各位的指正,感谢。
指针简单的,形象化的可以这么理解,就是一个地址,指向某一个内存单元:内存就像是一个旅店,每一个储存单元就是一个房间,储存单元中的数据就是旅客,而指针就是房间的门牌号。
先来看个代码,代码目的是统计输入的二维数组中的0元素个数,在主函数中输入数据,调用自定义函数统计,并打印0元素个数。
代码中有少量注释,后面我会把我认为难以理解的地方挑出来,逐一说说。
#include<stdio.h>
void tongji(int (*p)[4]) //定义一个数组指针(指向一个有4个元素的一位数组),作为形参
{
int i,j,n=0;
for(i=0;i<12;i++) //这里我偷了个懒,少些了一层循环,因为二维数组的在内存中是线性存放的
{
if(*(*p+i)==0) //判断每一个元素是否为0
n++;
}
printf("%d",n);
}
int main()
{
int i,j;
int a[3][4];
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",*(a+i)+j); //输入数据,存放到二维数组中
}
}
tongji(a);
}
首先我们要知道,二维数组的数组名是什么,如a[3][4],那么a就为数组第0行的起始地址。
那么 a+1 是第1行的首地址,为什么不是第一行第1个数据的地址呢,这其实跟 a 的类型有关;
在谭浩强的书上这么说C语言中的地址包括位置信息(就是内存的编号,1102这样的),同时还有所指向的数据的类型信息(就好比的房间是总统套房,还是普通标间);
所以上面的 a 它指向的是一个一维数组的首地址,在 a 上面的运算都是一排排的进行
搞懂了这些,再来分析分析代码
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",*(a+i)+j);
}
}
a+i就是第 i 行的首地址,
*(a+i)这个时候就是第 i 行第 0 列的地址了。注意注意,从这以后,再对这个东西进行加减,就是再某一列上动了,我是这么理解的,就降级了,以前管一行,现在只能管某一个了。
完成这俩个循环,输入数据的任务就完成了;
接下来我们来分析分析调用函数的实参,形参
tongji(a);
void tongji(int (*p)[4])
之前我们说到,a其实是指向数组首行的地址,是一行一行的来的,所以在将a作为实参传入自定义函数的时候,为了满足实参与形参类型一致,形参也应该定义为指向一个有4个元素的一维数组的数组指针,好像写的有点绕,
那我只好操起我垃圾的中式英语了: 形参 is a 数组指针 that 包含了4个元素。
接受完后,p就指向a了;
看到这儿,别着急,马上就写完了
for(i=0;i<12;i++)
{
if(*(*p+i)==0)
n++;
}
为什么这里遍历数组中的所有元素可以这么写的
前面我们说了这是的 p 是一个数组指针,在p上加减是换行;加个 * ,*p就降了一级,指向行里的某一个元素了,+i,就是顺序的往后面挪;一共12个,挪11次
* p+i 为指向单个元素的指针,再加个 * 就是该指针指向的元素的值了。