《C和C++代码精粹》——2.10 指针和多维数组

本节书摘来自异步社区出版社《C和C++代码精粹》一书中的第2章,第2.10节,作者: 【美】Chuck Allison,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.10 指针和多维数组

C和C++代码精粹
实际上,在C++中没有多维数组!至少对多维数组没有直接的支持。人们通常把一个一维数组看作一个向量,把一个二维数组看作一个表或者矩阵,把一个三维数组看作一个长方体。然而,数组的几何模型使明智地使用高维数组变得很困难,取而代之的是C++支持“数组的数组”的概念。例如,如果一个一维的整型数组为

int  a[4]={0,1,2,3};

它是一个有索引的整数集合:

《C和C++代码精粹》——2.10 指针和多维数组

我们通常把它描述成一个向量:

《C和C++代码精粹》——2.10 指针和多维数组

对一个二维整型数组,如:

int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,0,1}}

是像下面这样的向量集合:

《C和C++代码精粹》——2.10 指针和多维数组

或者,如果喜欢的话可写成:

《C和C++代码精粹》——2.10 指针和多维数组

这就是数组的集合。因此,a就是一个“3个具有4个整型元素的数组的数组”,a[0]就是这些具有4个整型元素的数组之一。由于在表达式中使用数组名时,它总是被解释为指向它的第一个元素的指针,所以一个诸如 a+1 之类的表达式就是“指向一个具有4个整型元素的数组的指针”,在这种情况下,该表达式将指向第二行(即a[1])。程序清单2.15中的程序说明了如何声明指向一个数组的指针,这样的指针可以在不改变下标语法的情况下,替换数组名。初学者容易错误地假设:指向整型数据的指针能代替一个整型数组名,就像以下程序:

int a[]={0,1,2,3},*p=a;
/*...*/
p[i]=...

那么,这样指向整型数据的指针的指针将会对二维数组进行同样的操作,就像下面:

int a[][4]={ {0,2,3,4},{4,5,6,7},{8,9,0,1}};
int **p=a;      /*受怀疑的指针转换*/
/*...*/
p[i][j]=...

要弄清以上做法为何不对,考虑一下表达式pi,根据“重要的指针原则2”,这就相当于:

*(p[i]+j)

也相当于:

*(*(p+i)+j)

程序清单2.15 说明在二维数组中指向一维数组的指针

// array8.cpp:    使用一个一维数组指针  
#include <iostream>  

main()  
{  
    int a[][4] = {{0,1,2,3},{4,5,6,7},{8,9,0,1}};  
    int (*p)[4] = a;        //指向包含4个整型成员的数组
    size_t nrows = sizeof a / sizeof a[0];  
    size_t ncols = sizeof a[0] / sizeof a[0][0];  

    cout << "sizeof(*p) == " << sizeof *p << endl;  
    for (int i = 0; i < nrows; ++i)  
    {  
        for (int j = 0; j < ncols; ++j)  
            cout << p[i][j] << ' ';  
        cout << endl;  
    }  
}  

//输出:  
sizeof(*p) == 16  
0 1 2 3   
4 5 6 7   
8 9 0 1

由于p是一个指向整型数据的指针,所以表达式 p+i 往 p后面移动的距离等于i个指针的大小,而不是 i 行(我们需要移动 i 行)。显然,我们需要的指针类型是 p 所指向的指针具备一个行的大小,因此 p 必须是一个行指针,也就是说它指向一个大小合适的数组。因此,有趣但又有逻辑性的语法为:

int (*p)[4]=a;

根据p的这个定义,编译器依据下面的步骤来求表达式((p+i)+j)的值:

1.p+i

这一步计算行指针,该行超出行 p 当前所指向的 i 行。

2.*(p+i)

这是具体的行(是一个数组)。

3.由于数组 *(p+i)不是 sizeof 或者 & 运算的操作数,所以它被指向它第一个元素的指针所替代,即 &ai ,这是一个指向整型(int)的指针。

4.&ai+j

因为&ai是一个指向整型(int)的指针,加上j就把这个指针向前移动了j个整型数据单位,结果是&ai。

5.*&ai

这就是整型a[i] [j]。

表2.1总结了指针和二维数组的这种关系,注意,不要因为a+1和a[1]有同样的值(0×8)而得出以下的结论:

a[i]==a+i  //  错误!

它们仅仅在数值上相等,而类型却不一样,因为sizeof(a+1)==2(一个指针),而 sizeof(a[1])= =8(一个有4个整型数的数组)。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

上一篇:区块链开发(三)以太坊客户端命令行选项汇总


下一篇:指针与多维数组深度剖析