第四章 数组和指针 (part4) 多维数组

严格地说,C++ 中没有多维数组,通常所指的多维数组其实就是数组的数组:


          // array of size 3, each element is an array of ints of size 4
          int ia[3][4];

在使用多维数组时,记住这一点有利于理解其应用。

如果数组的元素又是数组,则称为二维数组,其每一维对应一个下标:

     ia[2][3] // fetches last element from the array in the last row
第一维通常称为行(row),第二维则称为列(column)。

C++ 中并未限制可用的下标个数,也就是说,我们可以定义元素是数组(其元素又是数组,如此类推)的数组。


多维数组的初始化

和处理一维数组一样,程序员可以使用由花括号括起来的初始化式列表来初始化多维数组的元素。对于多维数组的每一行,可以再用花括号指定其元素的初始化式:

     int ia[3][4] = {     /*  3 elements, each element is an array of size 4 */
         {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
         {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
         {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
     };

其中用来标志每一行的内嵌的花括号是可选的。下面的初始化尽管有点不清楚,但与前面的声明完全等价:

     // equivalent initialization without the optional nested braces for each row
     int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

与一维数组一样,有些元素将不使用初始化列表提供的初始化式进行初始化。下面的声明只初始化了每行的第一个元素:

     // explicitly initialize only element 0 in each row
     int ia[3][4] = {{ 0 } , { 4 } , { 8 } };

如果省略内嵌的花括号,结果会完全不同:

     // explicitly initialize row 0
     int ia[3][4] = {0, 3, 6, 9};

该声明初始化了第一行的元素,其余元素都被初始化为 0。

多维数组的下标引用

为了对多维数组进行索引,每一维都需要一个下标。例如,下面的嵌套 for 循环初始化了一个二维数组:

     const size_t rowSize = 3;
     const size_t colSize = 4;
     int ia [rowSize][colSize];   // 12 uninitialized elements
     // for each row
     for (size_t i = 0; i != rowSize; ++i)
         // for each column within the row
         for (size_t j = 0; j != colSize; ++j)
             // initialize to its positional index
             ia[i][j] = i * colSize + j;

当需要访问数组中的特定元素时,必须提供其行下标和列下标。行下标指出需要哪个内部数组,列下标则选取该内部数组的指定元素。了解多维数组下标引用策略有助于正确计算其下标值,以及理解多维数组如何初始化。
指针和多维数组

与普通数组一样,使用多维数组名时,实际上将其自动转换为指向该数组第一个元素的指针。

<Note>:

定义指向多维数组的指针时,千万别忘了该指针所指向的多维数组其实是数组的数组。

因为多维数组其实就是数组的数组,所以由多维数组转换而成的指针类型应是指向第一个内层数组的指针。尽管这个概念非常明了,但声明这种指针的语法还是不容易理解:

     int ia[3][4];      // array of size 3, each element is an array of ints of size 4
     int (*ip)[4] = ia; // ip points to an array of 4 ints
     ip = &ia[2];       // ia[2] is an array of 4 ints

定义指向数组的指针与如何定义数组本身类似:

首先声明元素类型,后接(数组)变量名字和维数。

窍门在于(数组)变量的名字其实是指针,因此需在标识符前加上 *

如果从内向外阅读 ip 的声明,则可理解为:*ipint[4] 类型——即ip 是一个指向含有 4 个元素的数组的指针。

<Note>:

在下面的声明中,圆括号是必不可少的:

     int *ip[4]; // array of pointers to int
     int (*ip)[4]; // pointer to an array of 4 ints

用 typedef 简化指向多维数组的指针

typedef 类型定义可使指向多维数组元素的指针更容易读、写和理解。以下程序用 typedef 为 ia 的元素类型定义新的类型名:

     typedef int int_array[4];
     int_array *ip = ia;

可使用 typedef 类型输出 ia 的元素:

     for (int_array *p = ia; p != ia + 3; ++p)
         for (int *q = *p; q != *p + 4; ++q)
              cout << *q << endl;
外层的 for 循环首先初始化 p 指向 ia 的第一个内部数组,然后一直循环到 ia 的三行数据都处理完为止。

++p 使 p 加 1,等效于移动指针使其指向 ia 的下一行(例如:下一个元素)。

内层的 for 循环实际上处理的是存储在内部数组中的 int 型元素值。

首先让 q 指向 p 所指向的数组的第一个元素。

p 进行解引用获得一个有 4 个int 型元素的数组,通常,使用这个数组时,系统会自动将它转换为指向该数组第一个元素的指针。

在本例中,第一个元素是int型数据,q指向这个整数。系统执行内层的for 循环直到处理完当前 p 指向的内部数组中所有的元素为止。

q 指针刚达到该内部数组的超出末端位置时,再次对p 进行解引用以获得指向下一个内部数组第一个元素的指针。

p 指向的地址上加 4 使得系统可循环处理每一个内部数组的 4 个元素。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值