最近在学习关于二维数组及数组指针的问题,看了好几篇大神们写的博客,茅塞一顿一顿的开了。理解了数组符号的含义以及数组指针,指针数组,等等概念。为了纪念一下,遂把我学到的知识记录下来。
首先是关于数组符号问题。
这里粘贴上http://blog.csdn.net/iu_81/article/details/1782642这篇博客的一些讲解,我觉得非常清晰。
设p是指向数组a的指针变量,若有:
p=a[0];
则p+j将指向a[0]数组中的元素a[0][j]。
由于a[0]、a[1]┅a[M-1]等各个行数组依次连续存储,则对于a数组中的任一元素a[i][j],指针的一般形式如下:
p+i*N+j
元素a[i][j]相应的指针表示为:
*( p+i*N+j)
同样,a[i][j]也可使用指针下标法表示,如下:
p[i*N+j]
例如,有如下定义:
int a[3][4]={{10,20,30,40,},{50,60,70,80},{90,91,92,93}};
则数组a有3个元素,分别为a[0]、a[1]、a[2]。而每个元素都是一个一维数组,各包含4个元素,如a[1]的4个元素是a[1][0]、a[1][1]、a[1]2]、a[1][3]。
若有:
int *p=a[0];
则数组a的元素a[1][2]对应的指针为:p+1*4+2
元素a[1][2]也就可以表示为:*( p+1*4+2)
用下标表示法,a[1][2]表示为:p[1*4+2]
特别说明:
对上述二维数组a,虽然a[0]、a都是数组首地址,但二者指向的对象不同,a[0]是一维数组的名字,它指向的是a[0]数组的首元素,对其进行“*”运算,得到的是一个数组元素值,即a[0]数组首元素值,因此,*a[0]与a[0][0]是同一个值;而a是一个二维数组的名字,它指向的是它所属元素的首元素,它的每一个元素都是一个行数组,因此,它的指针移动单位是“行”,所以a+i指向的是第i个行数组,即指向a[i]。对a进行“*”运算,得到的是一维数组a[0]的首地址,即*a与a[0]是同一个值
对于二维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推。因此,*a与a[0]等价、*(a+1)与a[1]等价、*(a+2)与a[2]等价,┅,即对于a[i]数组,由*(a+i)指向。由此,对于数组元素a[i][j],用数组名a的表示形式为:
*(*(a+i)+j)
指向该元素的指针为:
*(a+i)+j
上面的文字对数组的符号,特别是二维数组的符号做了非常清晰的解释。也就是说,当我们声明一个int型数组时,比如 int a[10]={NULL}此时,a是一个指针,它指向这个数组的首元素。再就是,二维数组其实只是一个比较奇葩的一维数组。奇葩之处在于,它的每一个元素都是一个一维数组。也就是说,当我们声明一个int b [3][4]时,它其实只有3个元素,分别是b[0][4],b[1][4],b[2][4],这里涂了颜色的地方,跟刚才的a是同样类型的东西,它们都是一维数组的指针。而b跟a不是同样类型的东西。b虽然也是指针,但b指的东西只能是b[0],b[1],b[2].
另外还有一点,就是*这个符号。在声明东西的时候,它表示这是一个指针。在其他地方,它表示“这个地址里面所存的元素”,可以看成是一种运算了,跟&正好相反。