数组名字本身就是一个指针,是一个指针常量。即a等
价于int*consta,因此你不能试图修改数组名的值。数组名
的值就是数组第一个元素的内存单元首地址,即a=&a[0]。
表达式中的数组名总是被编译器解析为指针,下标总是和
指针的偏移量相同。C语言中将数组的下标改写成指针偏移
量的主要原因在于指针和偏移量是底层硬件所使用的基本
类型。如a[i]中的i总被编译器解析为偏移量,所以a[i]总是
被改写成*(a+i)的形式,a是指向数组第一个元素的指针,加
上偏移量i,表示该指针向后移i个步长,然后取a+i所在单
元的内容。这样,我们就可以通过同类型的指针迭代
(++/--)来遍历整个数组。
3二维数组与指针
C语言规定
[3]
:任何维数的数组都可以看做是由比它少
一维的数组为元素组成的一维数组。例如inta[3][4]={
{1,2,3,4},{5,6,7,8},{9,10,11,12}};首先,C语言把a看做一维数
组,它有三个元素a[0]、a[1]、a[2],每一个元素代表一行;其次,
a[0]、a[1]、a[2]分别是三个一维数组,一维数组a[0]包含a[0]
[0]、a[0][1]、a[0][2]、a[0][3]四个元素;一维数组a[1]包含a[1][0]、
a[1][1]、a[1][2]、a[1][3]四个元素;一维数组a[2]包含a[2][0]、a[2]
[1]、a[2][2]、a[2][3]四个元素。换句话说,a是一个二维数组的
数组名,a数组包含3个元素:a[0]、a[1]、a[2],而每个元素又
是一个一维数组(由4个元素组成的一维数组)。可以认为
二维数组是“由一维数组为元素组成的一维数组”,即数组a
是由3个一维数组所组成,是“数组的数组”。
a是a[0]的地址,a[0]是a[0][0]的地址,*a等价于a[0],**a
等价于*a[0]等价于a[0][0]。a[0]+1也就是*a+1,是a[0][1]的
地址,所以*(a[0]+1)或*(*a+1)等价于a[0][1]……
a+1是a[1]的地址,a[1]是a[1][0]的地址,*(a+1)等价于a
[1],**(a+1)等价于*a[1]等价于a[1][0]。a[1]+1也就是*a+1是
2012.05
(
下旬刊
)
a[0][1]的地址,所以*(a[1]+1)或*(*(a+1)+1)等价于a[0]
[1]……
*(*(a+i)+j)或*(a[i]+j)等价于a[i][j]。
1245008
1
a[0]
a
a[0]
1245012
2
a[0]+1
1245016
3
a[0]+2
1245020
4
a[0]+3
1245024
5
a[1]
a+1
a[1]
1245028
6
a[1]+1
1245032
7
a[1]+2
1245036
8
a[1]+3
1245040
9
a[2]
10
a+2
a[2]
1245044
←a[2]+1
1245048
11
←a[2]+2
1245052
12
←a[2]+3
二维数组数据结构示意图
4指针数组与多级指针
[5]
由指向同一数据类型数据的指针为元素组成的数组叫
指针数组
[4]
。一维指针数组的定义形式为:
类型*数组名[元素个数];
例如,int*num[5];定义了一维指针数组num,它有5个
元素num[0]、num[1]、num[2]、num[3]、num[4],每个元素都是指
向整型单元的指针变量。
【例】指针数组和多级指针的用法。
#include
voidmain()
{
char*c[]={“enter-”,”newgang”,”point”,”firwu”};
char**cp[]={c+3,c+2,c+1,c};
char***cpp=cp;
printf(“n%s”,**++cpp);//第一个printf()语句
printf(“%s”,*--*++cpp+5);//第二个printf()语句
printf(“%s”,*cpp[-2]+3);//第三个printf()语句
printf(“%s”,cpp[-1][-1]+3);//第四个printf()语句
}
程序运行结果:
point-wugang
分析:本程序开始通过初始化,使得指针数组c中的c
[0]、c[1]、c[2]、c[3]分别指向字符串”enter-”,”newgang”,”point”
和”firwu”。cp也是一个指针数组,每个指针指向下层的“指
针元素”,即它们是指向“指向字符串的指针”的指针。通过
初始化使得cp[0]、cp[1]、cp[2]、cp[3]分别指向c指针数组中
的c[3]、c[2]、c[1]和c[0]。cpp是个三能指针,通过初始化使其
指向cp指针数组的第0个元素。此时的数据结构的存储布
局如下图所示。
理工
cpp
cp
c
enter-0
newgang0
point0
firwu0
数据结构示意图
当程序执行到第一个printf()语句时,**++cpp指向其一
个特定的地址,按优先级规则,表达式的执行顺序应该是*
(*(++cpp))。cpp开始指向cp[0],执行前置加1,使得cpp指向
cp[1],*cp[1]则指向c[2],*c[2]指向point字符串的首字符p;
故将point字符串输出。执行程序中的第二个printf()语句时,
由于执行第一个printf()语句时cpp已指向cp[1],
*--*++cpp+5表达式按其优先规则应该是(*(--(*(++cpp))))
+5,++cpp使cpp由原指向cp[1]变为指向cp[2],--(cp[2])使
其原来指向的c[1]转变为c[0],输出内容是c[0]所指向的地
址再加上5所指向的子字符串,即输出“-”。当执行程序中
的第三个printf()语句时,其表达式是*cpp[-2]+3,由于第二
个和第三个printf()语句的前置加1操作使得cpp已指向了
cp[2],此时用下标表示cpp[-2]相当于cp[0],而cp[0]指向的
是c[3],输出内容是c[3]所指向的地址再加上3所指向的子
字符串“wu”。当执行程序中的第四个printf()语句时,cpp[-1]
[-1]+3指出了输出内容的确切地址。由于cpp指向cp[2],所
以-1则使cpp指向cp[1],cp[1]指向c[2],再执行-1则使cp
[1]由指向c[2]变为指向c[1],此时c[1]指向的地址再加3,指向
字符串“newgang”的第三个字符开始的子字符串,就是输出
子字符串“gang”。
5结语
通过以上分析和实例,我们可以弄清指针和数组的内在
联系和用法,这里主要讲述了数组和指针类型的关系,通过
对它们之间关系的了解可以更加深入地把握数组和指针特
性的知识,从而避免程序设计中因使用不当而出现的各种
错误。
★基金项目:保山学院校级自然科学研究基金项目(项
目编号:09B003JK)
参考文献
[1]谭浩强.C程序设计[M].第4版.北京:清华大学出版社,2010:220-
230.
[2]林锐,韩永泉.高质量程序设计指南-C++/C语言[M].第2版.北
京:电子工业出版社,2003:166.
[3](美)HerbertSchildt.C语言大全[M].第1版.郭兴社,戴建鹏,编译.
1990:131-137.
[4]赵家刚,李俊荻.C语言程序设计[M].第1版.西安:西安交通大学
出版社,2010:140.
[5]赵海廷.汉化TurboC程序设计[M].第1版.1997:204-206.
编辑胡俊龙
87
评论列表(0条)