4.5 指针与数组

    C++中,数组和指针的关系十分密切,两者的内部处理方式几乎是等价的。访问数组中的元素有下标和指针两种形式,两者是通过前面介绍的指针算术机制相对应的。

    4.5.1 数组名指针

    C++编译器将数组名解释为指针,请看代码4.8。

    代码4.8 数组名指针ArrayName


    <—————————————文件名:example408.cpp——————————————> 01 #include<iostream> 02 int main() 03 { 04 using namespace std; 05 int sz[5];//创建一个大小为5的int型数组 06 for(int i=0;i<5;i++){ 07 sz[i]=i;//依次对数组中的元素赋值 08 } 09 cout<<"sz:"<<sz<<endl;//输出数组名 10 cout<<"&sz[0]:"<<&sz[0]<<endl;//输出数组第一个元素的地址 11 cout<<"sz:"<<(sz)<<endl;//数组名可看成是指向首元素的常量指针 12 cout<<"(sz+3):"<<((sz+3))<<endl; 13 return 0; 14 }

    输出结果如下所示。


    sz:0012FF6C &sz[0]:0012FF6C *sz:0 *(sz+3):3

    【代码解析】代码中,声明一个大小为5,元素类型为int的数组sz,通过for循环结构对5个元素赋值,代码第9行通过输出数组名sz可以看出,编译器将数组名解释为数组内存区域的首地址,对一维数组来说,要实现对某个元素的访问,既可以用“数组名+下标”的形式,又可以用间接引用,即“*(数组名+偏移)”的形式。

    注意

    指针与整数的相加已经在前面讨论过,指针的移动单位取决于其指向的变量类型,而对数组这样一块连续的内存区域来说,对指针的加1操作使得指针从当前元素跳转到下一个元素。

    对代码4.8中的一维数组sz而言,sz[0]、sz[1]和sz[2]等都是一个变量名,但对二维和多维数组B来说,B[0]等是指针,指向以它们为名的广义向量。在介绍多维数组时,提及了元素在内存中的排列方式,以2×3×4的三维数组为例。


    B[0][0][0]->B[0][0][1]->B[0][0][2]->B[0][0][3] B[0][1][0]->B[0][1][1]->B[0][1][2]->B[0][1][3] B[0][2][0]->B[0][2][1]->B[0][2][2]->B[0][2][3] B[1][0][0]->B[1][0][1]->B[1][0][2]->B[1][0][3] B[1][1][0]->B[1][1][1]->B[1][1][2]->B[1][1][3] B[1][2][0]->B[1][2][1]->B[1][2][2]->B[1][2][3]

    诸如B[1][2][3]、B[0]0][0]都是变量名,对应着某个内存单元,数组名B是指针,指向数组所占整个内存区域的首地址,B的值为&B[0][0][0]。

    实际上,B[0]和B[1]也是指针,B[0]的值为&B[0][0][0],B[1]的值为&B[1][0][0],换言之,B[0]可以看做是下面一块内存区域的变量名。


    B[0][0][0]->B[0][0][1]->B[0][0][2]->B[0][0][3] B[0][1][0]->B[0][1][1]->B[0][1][2]->B[0][1][3] B[0][2][0]->B[0][2][1]->B[0][2][2]->B[0][2][3]

    说明

    将上例中的B[0]看成一个整体,比如替换成A,是不是更好理解一些。

    同样,B[1][1]等也是指针,其值为&B[1][1][0],B[1][1]可以看成是下面一块内存区域的变量名。


    B[1][1][0]->B[1][1][1]->B[1][1][2]->B[1][1][3]对三维数组B而言,有以下关系成立。 B=&B[0]; B+1=&B[1]; …… B[0]=&B[0][0]; B[0]+1=&(B[0][1]); …… B[0][0]=&B[0][0][0]; B[0][0]+1=&B[0][0][1]; ……

    更高维的情况可依次类推。