谈C语言中指针、地址和数组的相互关系
2009-03-02刘林香许燕青江忠君
刘林香 许燕青 江忠君
[摘要]在学习C语言过程中,指针、地址和数组是最富有特色的内容,特别是指针、地址和数组之间相互关系更具有特色。掌握它们之间的相互关系将有助于C语言其他内容的学习,因此学好这部分内容是掌握C语言的关键。主要用图示法阐述指针和地址、指针和数组之间的联系。
[关键词]C语言 指针 地址 数组 图示法
中图分类号:TP3文献标识码:A文章编号:1671-7597(2009)0120049-01
指针是C语言中一个最重要概念之一,指针变量是用来存放另外一个变量地址,通过指针变量可以间接引用另外一个变量的内容。数组是由若干个元素按一定顺序关系组合而成的集合体,即数组中的每一个元素都属于同一个数据类型,数组名则是数组元素的首地址,用户在编程中用一个数组名和下标来唯一确定数组中的每一个元素。所以,指针、地址和数组以及它们之间的相互关系构成C语言最有特色部分。
一、指针和地址
(一)指针变量的定义
在程序中定义了一个变量,那么在计算机内不仅定义了该变量的类型、名称,而且还在内存中分配了一块存储区域,这块存储区域的首地址称为该变量的指针。变量的值就存放在这块区域之中,在计算机内部,通过访问或修改这块区域的内容来访问或修改相应的变量。Turbo C语言中,对于变量的访问形式之一,就是先求出变量的地址,然后再通过地址对它进行访问。
指针变量的一般定义为:
类型标识符*标识符;
其中“标识符”是指针变量的名字,标识符前加了“*”号,表示该变量是指针变量,而最前面的“类型标识符”表示该指针变量所指向的变量的类型。一个指针变量只能指向同一种类型的变量,也就是说,我们不能定义一个指针变量,既能指向一整型变量又能指向双精度变量。如定义了一个指针变量int*ip;说明该指针变量ip为指向整数的指针,用它存放整型变量的地址。
(二)指针变量的引用
指针变量中只能存放地址,因此,在使用中不能将一个整数赋给一指针变量。如:
int *ip;ip=80;这种赋值是错误的。可以这样定义:
int i=100,x;int *ip;
定义了两个整型变量i,x,还定义了一个指向整数的指针变量ip。i,x中可存放整数,而ip中只能存放整型变量的地址。通过地址运算“&”可以把i的地址赋给ip:
ip=&i
此时指针变量ip就指向整型变量i,假设变量i的地址为1600,这个赋值可理解为图1所示的联系。
可以通过指针变量ip间接访问变量i,如:
x=*ip;
运算符*访问以ip为地址的存储区域,而ip中存放的是变量i的地址,因此,*ip访问的是地址为1600的存储区域,它就是i所占用的存储区域,所以上面的赋值表达式等价于
x=i;
另外,指针变量和一般变量一样,存放在它们之中的值是可以改变的,也就是说可以改变它们的指向,假设
Int i,j,*p1,*p2;
i=10 ;
j=20 ;
p1=&i
p2=&j
通过图示法阐述如下:
如图2所示,采用图示法展示出普通变量i、j和指针变量p1、p2之间的关系,指针其实是内存地址,而内存中的单元是按字节编址(每个地址编码对应一个字节空间),从图中可以看出整型变量i和j分别占用两个字节的内存空间。同时也可以看出每个指针变量也是占用两个字节的空间,因为每个指针变量都是存储一个地址码。
通过指针访问它所指向变量的值是以间接访问的形式进行的,所以比直接访问一个变量要多费时间,而且不直观,因为通过指针要访问哪一个变量,取决于指针的值(即指向),例如“*p2=*p1;”实际上就是“j=i;”,前者不仅速度慢而且目的不明。但由于指针是变量,可以通过改变它们的指向,以间接访问不同的变量的值,这给程序员带来灵活性,也使程序代码编写得更为简洁、高效。
二、指针和数组
指针和数组有着密切的关系,任何能由数组下标完成的操作也都可用指针来实现,而且使用指针处理数据,有助于产生占用空间小,运行速度快且高质量的目标代码。
(一)指向数组元素的指针
在C语言中,数组的指针就是数组的起始地址(也就第一个元素的地址),如:
int a[10],*p;
对于数组a[i]表示数组a的第i+1个变量,a是数组名表示该数组的首地址,为常量,即a与&a[0]等价,而p=a则将数组a的首地址&a[0]赋给指针变量p。通过p来访问数组元素时要注意以下问题:
1.P,a与&a[0]它们是等价的,都表示数组a的首地址。
2.p[i]和a[i]都是代表该数组的第i+1个元素。
3.p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用*(p+i)和*(a+i)来引用对象元素。
4.表达式p+1为指向p的下一个存储单元,即a[0]下一个元素a[1]的存储单元,也就是p+1等价于&a[1]。
(二)指向二维数组的指针
为了说明问题,假设有如下程序段:
int a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}},i,j,*p;
P=&a[0][0];
A为二维数组名,此数组有3行5列,共15个元素。也可这样来理解,数组a由三个元素组成:a[0],a[1],a[2]。而每个元素又是一个一维数组,且都含有5个元素(相当于5列),例如,a[0]所代表的一维数组所包含的5个元素为a[0][0],a[0][1],a[0][2],a[0][3],a[0][4]。数组名a也代表二维数组的首地址,也可看成是二维数组第0行的首地址。a+1就代表第1行的首地址,a+2就代表第2行的首地址。如果此二维数组的首地址为1000,由于第0行有5个整型元素,所以a+1为1010,a+2也就为1020,如图3所示。
把a[0],a[1],a[2]看成是一维数组名,可以认为它们分别代表它们所对应的数组的首地址,也就是讲,a[0]代表第0行中第0列元素的地址,即&a[0][0],a[1]是第1行中第0列元素的地址,即&a[1][0],根据地址运算规则,a[0]+1即代表第0行第1列元素的地址,即&a[0][1],a[i]+j即代表第i行第j列元素的地址,即&a[i][j]。将指针p指向二维数组a的首地址,p+1就指向下一个元素,由于每行5个元素,p+i*5+j就是第i行第j列元素的地址。
参考文献:
[1]谭浩强,C程序设计(第二版),北京:清华大学出版社,1999.
[2]严桂兰,C语言程序设计与应用教程,福建:厦门大学出版社,2001.