下标从0开始因为数组名本质是指针,a[i]等价于*(a+i),0偏移对应首地址,省去每次减1运算,符合硬件按字节偏移的特性及c语言不做隐式转换的设计哲学。

因为数组名本质是指针,a[i] 就是 a + i,下标直接当偏移量用——从 0 开始省掉每次减 1 的运算,底层更干净,编译器也更省事。
为什么 a[0] 对应首地址而不是 a[1]
数组名 a 在绝大多数上下文中退化为指向首元素的指针。所以 a[0] 等价于 *(a + 0),就是解引用首地址;a[1] 是 *(a + 1),即跳过 1 个元素大小后的地址。
- 如果下标从 1 开始,
a[1]得写成*(a + 1 - 1),每次访问都多一次减法 - 硬件不认“第几个”,只认“偏移多少字节”,
0是最自然的起始偏移 - C 语言设计哲学:不做隐式转换,不替你多算一步
for (int i = 0; i 这个习惯不是凑巧
它和左闭右开区间 [0, n) 完全匹配,边界计算干净:
i 直接对应合法索引范围,不用写 <code>i- 两个相邻子数组,比如
[0, k)和[k, n),端点自然衔接 - 空数组时
n == 0,循环体一次不进,逻辑自洽 - 若从 1 开始,就得写
for (int i = 1; i ,边界条件变笨重
越界访问时 a[n] 为什么特别危险
a[n](n 为数组长度)不是“最后一个元素”,而是**第一个越界位置**,它踩在合法内存块的紧邻右侧,极易覆盖关键数据:
-
int arr[3]占 12 字节(假设 int 为 4 字节),arr[3]地址 =&arr[0] + 12,刚好落在该变量分配区域之外 - 这个地址可能属于下一个局部变量、函数返回地址,甚至栈帧控制信息
- 读
arr[3]可能拿到垃圾值;写arr[3] = 42可能静默破坏其他变量,调试时难以复现 - 不同平台/编译器对越界行为处理不同——有的崩溃,有的看似正常,但隐患已埋下
真正容易被忽略的不是“为什么从 0 开始”,而是:下标 i 是否始终落在 [0, size) 内,这个检查往往被当成理所当然,直到某次越界改写了某个无关变量,程序在奇怪的地方崩掉。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











