C语言中的指针和数组

2010年10月19日 由 edsionte 留言 »

下面的内容节选自由我所执笔的会议记录。对于本文的不足之处,各位可以提出自己的看法。

Q1:指针和数组到底是怎么一回事?

A:指针和数组有本质的不同。指针就是一个内存地址,在32位系统下,一个指针永远占4个字节;数组是一块连续的内存空间,我们从一个已定义的数组中可以获得数组大小以及这块连续内存空间的起始地址。这个起始地址即数组首元素的地址,更具体的说是数组中首个元素的首地址。

在C语言中,只有一维数组。但是,当一个一维数组的元素是仍然是一维数组时,就形成了所谓的一维数组。如何印证这一点?二维数组在内存中的存储方式仍然是按照一维数组那样线性存储的,只不过这个数组的元素按照另一个一维数组线性存储。多维数组照此类推。

Q2:我还能获得关于数组和指针更详细的说明吗?

A:当然可以。

我们通常会这样使用一个指针:

int a[5];
int *p=a;

我们首先定义了一个指向int类型的指针p,在定义p的同时将其初始化为a;通常我们将这种行为称为“p指向一个大小为5的整形数组a”。事实上,我们可以更具体的想一下:p真的指向整个数组吗?当然不是。p只是指向一个int型变量而已。在这个例子中,p指向的是a数组的首元素。换句话说,p存储的是&a[0]。另外,p是变量,我们可以对p进行自加自减(在a数组有效的范围内),让p指向a数组的其他元素。换句话说,p可以存储整个数组中任意一个元素的地址(更具体的是这个元素的首地址)。而数组名a虽然也是个地址,但是它是一个常量,它永远存储的是数组的首地址,不可改变。

对于上述所言的p指针,我们可以通过指针方式*(p+i)和下标方式p[i]访问数组。对于数组名a而言,我们也可以通过*(a+i)和下标方式a[i]来访问数组。对于p指针而言,以指针方式访问数组的过程是这样的:我们通过p指针首先获取这个数组的首地址,然后加上i个偏移量,得到数组中第i个元素的地址,最后通过引用,得到具体的值。而对于p[i]这种下标访问方式,最终还是会被转化成上述指针访问方式。对于数组名a而言,与p方式相同。

另外还要注意,上述所说的i个偏移量,并不是加上i个字节那么简单;而是i个元素的总字节数。因此,给指针p加上一个整数和给指针p的二进制表示形式加上同样的整数,两者的含义是截然不同的。
另外,刚说到a是一个常量的问题,我想到了const关键字。上次在现代软件工程课程上,我听到有的同学说const所修饰的是常量。const修饰的当然是一个变量,只不过这个变量是只读的,即便这个变量的特性和常量相似。

Q3:对于数组a[3][4],我该如何理解更多的信息?

A:我们首先可以获知以下信息:数组a是一个包含有3个元素的数组,每个数组元素是一个大小为4的一维数组。因此,我们通常说这个数组有三行四列(但是你要清楚:内存中并不会出现3*4的那样的表格)。具体来说,二维数组a有以下三个元素:a[0],a[1],a[2];每一个元素又都是一个一维数组。对于一维数组a[0]来说,它又有4个元素:a[0][0],a[0][1],a[0][2],a[0][3];这4个元素是int型的。

以上就是关于这个数组的基本结构,下面从指针的角度来分析这个数组。

对于上述的数组名a,我们称为指向指针的指针(a是一个常量)。对于一维数组我们知道,数组名是数组中首元素的地址。对于上述所言的数组a,a当然也是这个数组首元素的地址。那么,数组a的首元素是什么?对了,就是a[0]。那么a这个指针存储的就是a[0]的地址,即a等价于&a[0]。那么a+i也就很明显了:a[i]的地址。再来想a[i]是什么?它是数组a中第i个元素。在数组a中,第i个元素是什么?它是一个大小为4的一维数组。对应到上述所言的“三行四列”,a+i即是指向第i行的指针。可以看到,i这个偏移量此刻是以行为单位的。

我们上述已说明,a+i指向a[i],a[i]是一个一维数组。a+i是一个指向指针的指针,那么现在取出a+i的值,也就是*(a+i)。从我们所说的“指向指针的指针”来看,*(a+i)也是一个指针,但是这个指针指向什么?它指向数组a[i]的首元素的地址,也就是a[i][0]的地址,即&a[i][0]。那么数组a[i]中第j个元素的地址是什么?那就是*(a+i)+j,即&a[i][j]。当然,也可以这么写:a[i]+j。

另外要说明的是,上述的a+i和*(a+i)的内存地址其实是相同,但是含义是完全不同的。具体原因,你可以从上面的陈述中得到答案。

Q4:难道指针就只有这么多内容吗?

A:当然不是。关于指针更高级的使用,还有指向一维数组的指针;指针数组;函数指针。可能它们的定义方式会让你迷惑,但是,无论如何,它们本质上仍然是指针。先了解最基本的指针,然后再理解这些高级指针就简单了许多。

上述Q1~Q3从某种角度来说,叙述的过于罗嗦,甚至有时候必须得咬文嚼字;并且,必须在实践的基础上理解上述内容。我个人的建议是,指针部分必须建立在“理论——实践——理论”这样反复的过程中,否则——套用现在最fashion的话——“指针神马的一切都是浮云~”。

广告位

发表回复

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key