由二维数组元素a[i][j]的地址有多种表示形式,数组元素a[i][j]也有以下三种等价表示形式:*(a[i]+j)、*(*(a+i)+j)、(*(a+i))[i]。特别是对于a[0][0],它的等价表示形式有*a[0]和**a。数组元素a[i][j]的地址也有三种等价的表示形式:a[i]+j、*(a+i)+j、&a[i][j]。
也可以定义指向二维数组中某行由若干个元素所组成的一维数组的指针变量。如代码
int (*p)[4];
定义指针变量p能指向一个由四个int型元素组成的数组。指针变量p不同于前面介绍的指向整型变量的指针。在那里,指向整型变量的指针变量指向整型数组的某个元素时,指针增减1运算,表示指针指向数组的下一个或前一个元素。在这里,p是一个指向由四个整型元素组成的数组,对p作增减1运算,就表示向前进或向后退四个整型元素。用例子说明指向由若干个元素所组成的数组指针的用法,如有变量定义
int a[3][4],(*p)[4];
则赋值p=a+l,使p指向二维数组a的第二行,表达式p+l的值为指向二维数组a的第三行。同二维数组元素的地址计算规则相对应,若 P=a+1,则*p+j指向a[l][j];*(p+i) +j,或者p[i]则指向数组a的元素a[i+l][j]。二维数组名和指向数组的指针与数组元素位置之间的关系。
5.3 指针数组和多级指针
1.指针数组
当数组元素类型为某种指针类型时,该数组就是指针数组。指针数组的定义形式为
类型说明符 *数组名[常量表达式] ;
例如:
int *p[10] ;
定义指针数组p的每个元素都是能指向int型数据的指针变量,p有10个元素,它们是p[0] 、p[l]、…、p[9]。和一般的数组定义一样,数组名p也可作为p[0]的地址。
在指针数组的定义形式中,由于“[ ]”比“*”的优先级高,使数组名先与“[]”结合,形成数组的定义,然后再与数组名之前的“*”结合,表示此数组的元素是指针类型的。注意,在“*”与数组名之外不能加上圆括号,否则变成指向数组的指针变量。
引人指针数组的主要目的是便于统一管理同类的指针。如利用指针数组能实现对一组独立的变量以数组的形式对它们作统一处理。如有以下定义:
in a,b,c,d,e,f;
int *apt[]={&a,&b,&c,&d,&e,&f};
下面的循环语句能顺序访问独立的变量a、b 、c、d、e、f;
for( k=0; k<6;k++)
printf(“%d\t”,*apt[k]);/*其中*apt[k]可写成**(apt+k)*/
当指针数组的元素分别指向二维数组各行首元素时,也可用指针数组引用二维数组的元素。以下代码说明指针数组引用二维数组元素的方法。设有以下代码:
int a[10][20] ,i;
int *b[10];
for(1=0;i<10;i++)/*b[i]指向数组元素a[i][0]*/
b[i]=&a[i][0] ;
则表达式a[i][j]与表达式b[i][j]引用同一个元素,即从指针数组方向来看,因b[i]指向元素a[i][0],*(b[i]+j)或 b[i][j]引用元素a[i][j]。
另外,当指针数组的元素指向不同的一维数组的元素时,也可通过指针数组,如同二维数组那样引用各一维数组的元素。如以下代码所示:
char w0[ ]=“Sunday”,w1[ ]=“Monday”,w2[ ]=“Tuesday”,
w3[ ]=“Wednesday”, w4[ ]=“Thursday”, w5[ ]=“Friday”,
w6[ ]=“saturday”;
char *wName[ ]={w0,wl,w2,w3,w4,w5,w6 };
则语句for(i=0;i<=6;i++)
printf(“%s\n”, wName[i]);
输出星期的英文名称。代码wName[2][4]引用字符w2[4],其值为'd’。
以下例子把一维数组分割成不等长的段,通过指针数组,把一维数组当作二维数组来处理。
# include
# define N 8
int p[N*(N+l)/2],i,j,*pt[N] ;
void main()
{ for(pt[0]=p, i=l;i
pt[i]=pt[i-1]+i;