💻 第六章 与数据结构成为好朋友的七个要点
📄 一句话概括

数组=同类型数据排成一排连续存放、按下标直达——下标从 0 起,因为它是【偏离起点的格数】。

📝 本节和前面几节的关系

格子关系焊牢了,第一种数据结构登场:数组——最常用、也几乎是一切其他结构的舞台。

一、数组的三个特征

同类型:每格装的东西一样大(都是 int、都是 char); 连续存放:在内存里一格贴一格,不留缝; 按下标访问:scores[2] 一步直达,不用从头数。 三个特征是一体的:正因为同类型等大+连续,地址才能用公式算——起点地址+下标×格子大小,一步跳到任意格。

二、下标为什么从 0 开始

初学最别扭的一件事。原因就藏在地址公式里:下标其实是【偏离起点的格数】——第 1 格偏移 0 格、第 2 格偏移 1 格。 从 0 数起,地址公式最简洁;从 1 数起反而要处处减一。语言设计者选了让机器省事的那种。

三、越界:数组的规矩

5 格的数组最大下标是 4——访问下标 5 就是越界。 有的语言会报错拦下(Python 的 IndexError),C 语言不拦、直接读写隔壁格子——缓冲区溢出这个经典安全漏洞就是这么来的(19 课信息安全课的主角之一)。

四、动手 Demo:数组的下标与越界

建一个 5 格数组,走一遍按下标读写、再故意越界看报错。

# 数组(Python 里用列表演示)
scores = [88, 92, 79, 95, 83]
print(scores[2])      # 下标 2 -> 第 3 格
scores[0] = 90        # 按下标改值
print(scores)
print(scores[5])      # 越界!

实跑输出:

--------------------------------------------------------------------
要点 2——数组:排成一排的同类型格子
--------------------------------------------------------------------

数组三个特征:**同类型**、**连续存放**、**按下标访问**(下标从 0 起)。

一个 5 格的 int 数组:
    下标 0 <- 值 88
    下标 1 <- 值 92
    下标 2 <- 值 79
    下标 3 <- 值 95
    下标 4 <- 值 83

按下标取值: scores[2] = 79 (第 3 格, 因为从 0 数起)
按下标改值: scores[0] = 90 后 -> [90, 92, 79, 95, 83]

[重要规矩] 越界会出事:
    访问 scores[5] -> 报错 IndexError! (最大下标只有 4)

  特征         好处                     代价
  --------------------------------------------------------------
  连续存放     按下标一步跳到任意格     中间插队要整体挪
  同类型       每格一样大, 好算地址     想混装就得用结构体(6.6)

为什么下标从 0 开始?——下标其实是【偏离起点的格数】:
    第 1 格偏移 0 格, 第 2 格偏移 1 格……数组地址 = 起点地址 + 下标 x 格子大小。

报错信息 IndexError 就是在提醒【你的下标出了界】——读报错先看下标值。 【⚠️ 2026 现状】Python 的列表其实比 C 数组更高级(可混装、可变长),但下标从 0、按位直达这两个核心行为一脉相承。

30 秒实验

  1. 心算:int 数组每格 4 字节、起点地址 1000,下标 6 的地址是多少?(1024)
  2. 故意写一个越界访问,读一遍报错信息——习惯从报错定位下标错误。

常见误区

  1. 以为 5 格数组的最后一个是下标 5——是 4,从 0 数起。
  2. 以为越界顶多读到垃圾值——在 C 语言里它是严重安全漏洞的入口。
自测三问(点开对答案) 1. 数组的三个特征? —— 同类型、连续存放、按下标访问。 2. 下标为什么从 0 开始? —— 下标=偏离起点的格数,地址公式(起点+下标×格大小)最简洁。 3. 缓冲区溢出与数组什么关系? —— 越界写数组却不被拦截(如 C 语言),就会覆盖相邻内存——安全漏洞的经典来源。

相关笔记