3.4指向数组的指针
unsigned
char a[]={0x00,0x10,0x20,0x30,0x40,0x50,0x60};
unsigned
char b[9][3]={0};
unsigned
char (*p)[3];
//数组指针,指向一个包含3个元素的一维数组的指针
//*******unsigned
char *p[3];
//指针数组,数组中的每个元素都为指针********//
p=b;
//*******************铁片外0中断函数********************
tiepian() interrupt 0 using 1
{
unsigned
char k=3;
EX0=0;
a[6]++;P1=a[6];
while(k){*(*(p)+(k-1))=a[k+2]; k–;}
p++;
EX0=1;
}
前面说过,指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数据结构的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢?因为数组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址,也就找到了该数组或函数。这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可。这样做,将会使程序的概念十分清楚,程序本身也精练,高效。在C++语言中,一种数据类型或数据结构往往都占有一组连续的内存单元。用“地址”这个概念并不能很好地描述一种数据类型或数据结构,而“指针”虽然实际上也是一个地址,但它却是一个数据结构的首地址,它是“指向”一个数据结构的,因而概念更为清楚,表示更为明确。
如果我们有如下数组定义:
int *ia[]={0,1,1,2,3,5,8,13,21};
那么,数组名ia就表示数组中第一个元素的地址,它的类型是数组元素类型的指针。在ia这个例子中,它的类型是int *。因此,下面两种形式是等价的,它们都返回数组的第一个元素的地址:
ia或者是&ia[0];
类似的,为了访问相应的值,我们可以取下列两种方式之一。
*ia或者是ia[0]; //两者都得到第一个元素的值
要访问数组的第二个元素,我们可以通过两种方式:*(ia+1)或者是ia[1];但是下面的表达式:*ia+1却与之完全不同。
由于解引用操作符比加法运算符的优先级高,所以它先被计算。解引用ia将返回数组的第一个元素的值。然后对其加1,实际上就相当于ia[0]+1。如果在表达式里加上括号,那么ia将先加1,然后解引用新的地址值。对ia加1将使ia增加其元素类型的大小,ia+1指向数组的下一个元素。
数组元素遍历可以通过下标操作符来实现,到目前为止我们一直这样做,或者我们也可以通过直接操作指针来实现数组元素遍历。
[例3.8]
#include
int main()
{
int ia[9]={0,1,1,3,5,8,13,21};
int *pbegin=ia;
int *pend=ia+9;
while (pbegin!=pend)
{
cout<
++pbegin;
}
}
pbegin被初始化指向数组的第一个元素。在while循环的每次迭代中它都被递增以指向数组的下一个元素,最难的是判断何时停止。在本例中,我们将pend初始化指向数组最末元素的下一个地址。当pbegin等于pend时,表示已经迭代了整个数组。
如果我们把这一对指向数组头和最末元素下一个元素的指针,抽取到一个独立的函数中,那么,就有了一个能够迭代整个数组的工具,却无须知道数组的实际大小(当然,调用函数的程序员必须知道)。
[例3.9]
#include
void ia_print(int *pbegin, int *pend)
{
while (pbegin!=pend)
{
cout<
pbegin++;
}
}
int main()
{
int_ia[9]={0,1,1,2,3,5,8,13,21};
ia_print(ia,ia+9);
}
下面我们以二维数组为例介绍多维数组的指针变量。
3.4.1多维数组地址的表示方法设有整型二维数组a[3][4]如下:
0 1 2 3
4 5 6 7
8 9 10 11
设数组a的首地址为1000,各下标变量的首地址及其值如图3.4.1所示。
在第二章中介绍过,C++语言允许把一个二维数组分解为多个一维数组来处理。因此数组a可分解为三个一维数组,即a[0],a[1],a[2],每一个一维数组又含有四个元素。例如a[0]数组,含有a[0][0],a[0][1],a[0][2],a[0][3]四个元素。