C——数组与指针

多维数组

 

1.       对两维数组的理解

对于Float rain[5][12],把它理解为有这样一个数组,它的可以表示为rain[5],而其中的每一个元素(总共有5个)是另外一个数组,这个数组有12float类型的数据。

所以rain的首元素rain[0]是一个包含12float数值的数组,且rain[1],rain[2]等等也是如此。换言之,rain是包含5个元素(每一个元素又是包含12float数的数组)的数组。

 

2.       对于两维数组的地址计算

根据刚才的分析,可以得出以下结论。

如果有数组int a[3][3], 32位机子上运行,且假设a的地址为2000,那么a[1]的地址就是20122000 + 4 * 3),而且a[1]的地址就是a[1][0]的地址,正如a的地址就是a[0][0]的地址(数组名其实就是该数组首元素的地址)。

另外,a[2][1] == *(*(a + 2) + 1) , 理解两维数组的关键是a[1]是个int *型指针,因为a[1]是指向其首元素a[1][0]的指针,而a[1][0]int * 型。

 

3.       如何将数组作为参数传递到函数

处理数组的函数其实使用指针指针作为参数的。在C中,a[i]在后台就是被解析为*(a + i)

(1)     一维数组

方法一,如果有float a[3],那么对应的函数原型至少为 int sum(float * a, int n),其中float * a 是因为以后将会传入数组名,而数组名就是数组第一个元素的地址,所以要与之匹配,对于这个例子,数组的第一个元素是float型,所以如果传入参数的话就应该是float*. int n是为了传入这个数组的大小,防止函数内越界。

 

方法二,如果有float a[3],那么对应的函数原型至少为 int sum(float * a, float * end)

调用如下 sum(a , a + 3)。然后需要在sum中做的事情是判断,注意在做while的时候的判定条件是 while ( a < end),其中千万不能用等号,因为a的最后一个元素为a[2]

 

(2)     两维数组

利用指针数组(形似int (*p)[2],函数原型写成 int sum( int (*p)[2], int rows)。其中要已知两维数组的列数为2,行数作为一个参数传进sum.

 

4.       指针可以使用的基本操作

(1)       赋值

(2)       求值(*操作符)

(3)       取指针的地址(&操作符)

(4)       将整数加给指针(包括自加)

(5)       从指针中减去一个整数(包括自减)

(6)       求差值——通常对分别指向同一个数组内两个元素的指针求差值,以求出元素之间的距离。

(7)       比较——前提是两个指针具有相同的类型

 

5.       对指针的加减法运算

C中,对一个指针加1的结果是对该指针增加1个存储单元(即它所指向的对象的字节大小)。比如说有int * p. 如果p的地址是2000,那么++p的结果是2004(在32位机子上,int占用4个字节)。

对于数组而言,由于这个特性,地址会增加到下一个元素的地址。

   于是,如果有double dates[10],则显然 (date + 2) == &dates[2],而且*(dates + 2) == dates[2]

 

注意,这里是对指针的加减法,虽然dates代表dates[0]的地址,但是它毕竟不是指针,而是地址的常量。所以语句dates++是违法的。

 

6.       关于const int * pint  * const p

前者constint *, p所指向的地址是不能够被改变了,但是这个地址所代表的内容却是可以改变的。后者constp,即p的内容(*p)是不能够被改变了,但是p所指向的地址却是可以转换的。

 

7.       指针数组与数组指针

关键在于[]的优先级高于*

(1)     Int (*pz)[2]

pz是一个指针,指向一个int[2]的匿名数组。

 

(2)     Int * pz[2]

Pz是一个数组,他有2个元素,而且每一个元素是int *型。

 

8.       指针的兼容性

指针赋值非常严格,只能够赋给相同类型的值。

例如有如下声明:

Int * pt;

Int (*pa)[3];

Int ar1[2][3];

Int ar2[3][2];

Int **p2

那么有如下结论

Pt = & ar1[0][0] //成立

Pt = ar1[0] //成立 ,因为ar1[0]就是int * 型指针。可以这样理解。 &Ar1[0][0] == *(ar1 + 0) + 0

Pt = ar1 // 非法,因为ar1是指向由3int值构成的数组的指针,说白了其实是一个int[3]型的指针,而不是int *型指针。Ar1是指向ar1[0]的指针,而ar1[0]是一个int[3],所以ar1int[3]型指针。

Pa = ar1 // 成立,理由见上

Pa = ar2 //不成立, 因为paint[3]型指针,而ar2int[2]型指针

P2 = &pt //成立

*p2 = ar2[0] //成立,因为ar2[0]int * 型指针,因为ar2[0]是指向其首元素ar2[0][0]的指针

P2 = ar2 //不成立,p2int **,ar2int[2]型指针。

posted @ 2009-10-10 10:07  aicro  阅读(264)  评论(0)    收藏  举报