女孩和机器人一起思考

一起动脑筋 · 先看一个小故事

五个储物格只贴了 0 到 4 的标签,机器人却要打开 5 号格。图上根本没有这个位置。

把过程摊开来看

沿着编号看一遍,再用自己的话讲一遍
  1. 先看长度5
  2. 合法范围0 到 4
  3. 访问前检查下标必须小于 5

数组越界就是访问了有效范围之外的位置。

普通 C++ 数组不会自动帮你补一个新格子,也不保证每次越界都立即报错。可能看似正常,却已经不可靠。

01什么叫越界?

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

合法下标只有:

0, 1, 2, 3, 4

访问 a[5]a[-1] 都属于越界。

02越界以后会发生什么?

最危险的地方是:结果不固定。

看似正常

暂时没有明显问题。

奇怪数值

读到不属于数组的数据。

破坏数据

写坏旁边的内存。

程序崩溃

触发访问错误。

03为什么 C++ 不一定自动报错?

普通数组下标访问通常不会自动进行运行时边界检查。

这给 C++ 带来很高的控制力和性能,但也要求程序员保证下标合法。

04循环最容易在哪里写错?

for (int i = 0; i <= 5; i++) {
    std::cout << a[i];
}

i == 5 时会访问 a[5]

正确范围应该是:

for (int i = 0; i < 5; i++)

05有没有会检查边界的工具?

std::arraystd::vector 提供 .at()

v.at(i)

如果下标超出范围,会通过异常报告错误,而不是默默进行未定义访问。

但普通 [] 通常仍不做这种检查。

06怎样减少越界错误?

牢记范围

长度 n → 0 到 n-1。

统一管理长度

不要到处手写魔法数字。

画表追踪

检查循环变量最后会到哪里。

你已经知道了什么

  • 数组越界就是访问合法范围之外的元素。
  • 普通 C++ 数组越界属于未定义行为。
  • 没有崩溃也不代表代码正确。
  • 最常见错误是把 i < n 写成 i <= n
  • 使用容器的 at() 可以获得边界检查。

下一篇:二维数组:把数据排成一张表

轮到你来试一试

循环条件写 i <= 5,用 i 访问五元素数组,有哪些值不合法?

想好了吗?点开看解释

从 0 开始时,i 为 5 的那次不合法。条件应确保 i < 5;还要避免负下标。