🔷 第七章 数组、指针和引用
📄 一句话概括

二维数组=一张有行有列的表格(想成座位表或 Excel 就行)。int a[3][4] 表示 3 行 4 列、共 12 格。有意思的是:它在内存里其实还是一排连号的柜子,只是我们"在心里按行切开"来看它。

📝 本节和前面几节的关系

7.1 的数组是"一排柜子",这一节把柜子排成"一张网格"。它需要的新知识并不多——访问它要两层 for(5.4 循环嵌套在这里二次上岗),初始化多了一层花括号。真正的重点是记住那句内存真相:二维数组只是"看起来像表格",底层仍是 7.1 讲的连续一排。

一、从"一排"到"一张表"

一维数组够用吗?看这几个场景:

场景 一维数组的尴尬 二维数组的顺眼
3 个学生 × 4 门课的成绩 12 个值挤成一排,谁是第几个人的第几门?全靠心算 score[3][4]:第 i 人的第 j 门
围棋/五子棋棋盘 19×19 = 361 格挤成一排 board[19][19]:第 i 行第 j 列
一张图片的像素 宽 × 高 挤成一排 pixel[高][宽]

共同点:数据天然有两个方向(行、列)。用一维数组硬塞,就得自己做"乘法换算"(第 i 人第 j 门 = 第 i*4+j 个);二维数组让下标直接对着行和列,读起来就是"某人的某门课"。

二、内存真相:它还是一排

这是本节最值钱的一句话:二维数组在内存里也是连续的一排,只是"按行优先"铺开。

        ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
int     │[0]0│[0]1│[0]2│[0]3│[1]0│[1]1│[1]2│[1]3│[2]0│[2]1│[2]2│[2]3│
a[3][4] └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
         └─── 第 0 行 ────┘└─── 第 1 行 ────┘└─── 第 2 行 ────┘

行优先:先把第 0 行从左到右摆完,接上第 1 行,再接第 2 行。所以 a[0][3] 的右边紧挨着的就是 a[1][0]。

这一点马上就有用:7.2.3 的"不分行初始化"就是按这个顺序填的;7.5.2 的"用指针遍历二维数组"也是靠它才走得通。

三、本节三篇分工

要做的事 小节
声明:订多大一张表 7.2.1
引用:怎么取"第 i 行第 j 列" 7.2.2
初始化:怎么把整张表一次摆好 7.2.3

四、动手 Demo:打印一张 3×4 成绩表

#include <iostream>
using namespace std;

int main() {
    int score[3][4] = {                 // 3 个学生 × 4 门课(7.2.3)
        {85, 92, 78, 90},
        {60, 75, 88, 95},
        {100, 55, 70, 80}
    };

    for (int i = 0; i < 3; i++) {       // 外层管"行"(5.4)
        cout << "学生 " << i + 1 << ":";
        for (int j = 0; j < 4; j++) {   // 内层管"列"
            cout << score[i][j] << "\t";
        }
        cout << endl;
    }
    return 0;
}

看到什么算成功:三行四列整整齐齐,每行是一位学生的四门课成绩。

读代码:score[i][j] 读作"第 i 行第 j 列",和坐标、Excel 的读法完全一致。外层变量习惯用 i(行)、内层用 j(列),这是全行业通用习惯——别随手写成 x/y,看代码的人会先入为主地误解(5.4 里说过两层变量名必须不同)。

30 秒实验:把外层循环的 i < 3 改成 i < 4,重跑——你会看到第 4 行打印出一串乱七八糟的数。这就是 7.1.2 的越界:二维数组超出行数,照样不报错。

五、常见误区

  1. "二维数组在内存里是一张真正的表格"——不是。它是一排连续内存,只是下标写法让它看起来像表。搞混这点,7.5.2 的指针遍历就没法理解。
  2. "行和列可以随便命名、随便颠倒"——语法上没错,但 a[行][列] 是约定俗成的读法。把行写成 j、列写成 i,自己都会绕晕。
  3. "二维数组能装不同长度的行"——不能。int a[3][4] 的每一行都恰好 4 格,规规矩矩的矩形。想装"长度不一的表"(比如每行字数不同的名字表),得用 7.7 的指针数组。
  4. "二维就是极限了,还有三维吗"——有,语法照推(a[2][3][4]),但实际开发中三维以上很少见,本章只讲二维。
自测三问(点开对答案) 1. `int a[3][4]` 一共几格?——12 格(3 行 × 4 列)。 2. 二维数组在内存里是表格吗?——不是,是**按行优先连续铺开的一排**。 3. `a[0][3]` 在内存里的下一个是哪一格?——`a[1][0]`(第 0 行末尾紧挨着第 1 行开头)。

相关笔记