二维数组和指针
二维数组和指针1、二维数组和数组元素的地址定义如下。 int *p
a[3][4];
1 )二维阵列a由几个一维阵列组成,c语言定义的二维阵列实际上是一维阵列,该一维阵列的每个成员也是一维阵列。 在如上定义的a排列的情况下,可见a排列由a[0]、a[1]、a[2]三个要素构成,a[0]、a[1]、a[2]的各要素分别是由四个整数要素构成的一维排列。 可以使用a[0][0]、a[0][1]等引用a[0]的各个元素。 其他依次相同。 如第2节所述,在c语言中,在函数主体或函数外部定义的一维数组名称是地址常数,其值是数组第一个元素的地址,该地址的基本类型是数组元素的类型。 在以上二维阵列中,a[0]、a[1]、a[2]都是一维阵列名称,相似地表示地址变量,其值是二维阵列中各行的第一个元素的地址,并且基类型是阵列元素的类型。 因此,对于二维数组,a[0]这样的公式是非法的。 如果有表达式a[0] 1,则表达式中的1的单位必须为2字节。 在以上定义中,指针变量p的基类型为a[I](0I<; 与3 )相同,因此赋值语句p=a[i]; 合法。 a[i]也已知写作() ) ) aI ),因此也可以写作上述赋值语句) ) p=* ) aI )。
2 )二维数组名称和作为地址常数的二维数组名称都同样是保存地址常数的指针,其值是二维数组第一个元素的地址。 上述a数组中,数组名a的值与a[0]的值相同,但基本类型是具有4个整数元素的数组类型。 也就是说,a 0的值与a[0]的值相同,a 1的值与a[1]的值相同,a 2的值与a[2]的值相同,分别表示a数组中第0、第1和第2行的起始地址。 二维数组名称必须理解为一个行指针。 在表达式a 1中,数字1的单位必须是42字节,而不是2字节。 赋值语句p=a; 不合法。 因为p和a的基本类型不同。 同样,对于二维数组名称a也不能进行a,a=a i等运算。
3 )二维数组元素地址二维数组元素的地址可以根据式a[i][j]求出; 也可以用每行的起始地址表示。 在以上二维阵列a中,各元素的地址可以由各行的起始地址: a[0]、a[1]、a[2]等表示。 示例:地址a[0][0]可以用a[0] 0表示,地址a[0][1]可以用a[0] 1表示; 0i<; 3、0j<; 在4的情况下,a[i][j]的地址可以通过[1] a [ I ] [ j ] [2] a [ I ] j [3] * [ ai ] j [4] a [0] [4]的五种公式求出
)5) a[0] 4*i j
在上述公式中,a[i]、a[0][0]、a[0]的基本类型都是int型,基于此自动决定公式中常数1的单位为2字节。 但是,求出a[i][j]地址的公式不能写为a 4*i j。 由于a的基础类型是四个整数元素的数组类型,因此将自动确定常量1的单位为8字节。
2、从地址引用二维数组元素,有以下定义时: int
a[3][4],I,j; 以及0i<; 3、0j<; 在4的情况下,a阵列元素是(1) a(I ) j ) (2) ) (a ) I ) ) )3) * ) ai (j ) ) )4) ) ) a ) I )
在(2)中,在式* ) a[i] )中,由于a[i]的基模为int,所以j的偏移量为2j字节。
在(3)中,式() ) ) ) ) ) a基模型是4个要素的排列,I的偏移量是42i字节; 另一方面,*(aI )的基本模型为int,j的位移量仍为2j字节。
(4)中,) ) aI )以外的括号对是必不可少的。 () (aI ) )时,运算符) )的优先级高于)号,因此公式为() ) ) ) () ) **(aIj ) ) ) (a[i][j] )
在(5)中,a[0][0] 4*i j表示数组元素a[i][j]的地址,根据地址运算符*编号,式* ) a[0][0] 4*i j表示数组元素a[i][j]
3、创建指针数组引用二维数组元素有以下定义时: int *p[3],a[3][2],
I,j
; 这里,在指定符*p[3]中,也按照运算符的优先顺序,对[]的优先顺序高于*号,因此p首先与[]结合而构成p[3],p是一个数组名,系统打开与其连续的三个存储单元前面的*号表示数组p是指针型,其各要素表示基本型是int的指针。 如果满足条件,则为0i<; 在3的情况下,p[i]和a[i]的基本类型相同,p[i]=
a[i]是正当的赋值形式。
有以下循环时: for(I=0; i3; I ) p(I )=
a[i]; 这里,代入号码右边的a[i]是常数,表示a排列的各行的开头地址,代入号码左边的p[i]是指针变量,循环执行的结果,p[0]、p[1]、p[2]分别指向a排列的各行的开头此时,排列p和排列a关系如图所示
9.6所示。当p数组的每个元素已如图9.6所示指向a数组每行的开头时,则a数组元素a[i][j]的引用形式*(a[i]+
j)和*(p[i]+j)是完全等价的。由此可见,这时可以通过指针数组p来引用a数组元素,它们的等价形式如下:(1)*(p[i]+j)
(2)*(*(p+i)+j) (3)(*(p+i))[j] (4)p[i][j]
不同的是:p[i]中的值是可变的,而a[i]中的值是不可变的。
图9.64、通过建立一个行指针来引用二维数组元素若有以下定义:int a[3][2],
(*prt)[2];在这里,说明符(*prt)[2]中,由于一对圆括号的存在,所以*号首先与prt结合,说明prt是一个指针变量,然后再与说明符[2]结合,说明指针变量prt的基类型是一个包含有两个int元素的数组。在这里,prt的基类型与a的相同,因此prt=a;是合法的赋值语句。prt+1等价于a+1、等价于a[1]。当prt指向a数组的开头时,可以通过以下形式来引用a[i][j]:(1)
*(prt[i]+j) (2) *(*(prt+i)+j) (3)(*(prt+i))[j] (4) prt[i][j]
在这里,prt是个指针变量,它的值可变,而a是一个常量。
附:
#include "stdio.h"
void disp(int (*a)[3])
{
printf("%d",*(*(a+1)+1));
}
void main()
{
int
a[2][3];
a[0][0]=1;
a[0][1]=2;
a[0][2]=3;
a[1][0]=4;
a[1][1]=5;
a[1][2]=6;
disp(&a[0]);//也可以写作disp(a);
}