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

简介:

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

2.10 指针和多维数组

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

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

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

image

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

image

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

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

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

image

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

image

这就是数组的集合。因此,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个整型数的数组)。

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

相关文章
|
3天前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
21 0
|
1月前
|
算法 安全 C++
提高C/C++代码的可读性
提高C/C++代码的可读性
51 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
86 4
|
2月前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
2月前
|
存储 搜索推荐 C语言
深入C语言指针,使代码更加灵活(二)
深入C语言指针,使代码更加灵活(二)
|
2月前
|
存储 程序员 编译器
深入C语言指针,使代码更加灵活(一)
深入C语言指针,使代码更加灵活(一)
|
2月前
|
C语言
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
深入C语言指针,使代码更加灵活(三)
|
2月前
|
存储 C++
c++的指针完整教程
本文提供了一个全面的C++指针教程,包括指针的声明与初始化、访问指针指向的值、指针运算、指针与函数的关系、动态内存分配,以及不同类型指针(如一级指针、二级指针、整型指针、字符指针、数组指针、函数指针、成员指针、void指针)的介绍,还提到了不同位数机器上指针大小的差异。
61 1
|
2月前
|
存储 编译器 C语言
C++入门2——类与对象1(类的定义和this指针)
C++入门2——类与对象1(类的定义和this指针)
43 2
|
2月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
353 0
vsCode远程执行c和c++代码并操控linux服务器完整教程