「なぜ配列のインデックスは0から始まるんですか?」——プログラミングを学び始めた人が必ず抱く疑問だ。日常生活では「1番目」から数えるのに、なぜコンピュータだけが「0番目」から始まるのか。この問いの答えは、1960年代のメモリ管理にまで遡る。
0-indexedの技術的起源
配列が0から始まる最大の理由は、メモリアドレスの計算にある。配列の要素にアクセスするとき、コンピュータは次の計算を行う。
要素のアドレス = 配列の先頭アドレス + (インデックス × 要素サイズ)
もしインデックスが0から始まれば、先頭要素のアドレスは「先頭アドレス + 0」となり、追加の計算が不要になる。1から始めると、毎回「-1」する引き算が発生する。1960年代のCPUにとって、この1回の引き算は無視できないコストだった。
| 言語 | 配列の開始インデックス | 設計年 | 理由 |
|---|---|---|---|
| C | 0 | 1972年 | ポインタ演算との一貫性 |
| Java | 0 | 1995年 | C/C++との互換性 |
| [Python](/tag/python) | 0 | 1991年 | C言語の慣習を継承 |
| Fortran | 1 | 1957年 | 数学の添え字表記に準拠 |
| Lua | 1 | 1993年 | 非プログラマー向けの直感性 |
| MATLAB | 1 | 1984年 | 行列計算の数学的慣習 |
ダイクストラの数学的論証
1982年、コンピュータ科学の巨人エドガー・ダイクストラは手書きのメモ「Why numbering should start at zero」を発表し、0-indexedの数学的な優位性を論じた。
ダイクストラの主張はこうだ。自然数の連続する部分列を表現する方法は4通りある。
| 表記法 | 2, 3, 4を表す場合 | ダイクストラの評価 |
|---|---|---|
| a ≤ i < b | 2 ≤ i < 5 | 最も優れている |
| a < i ≤ b | 1 < i ≤ 4 | 下限が不自然 |
| a ≤ i ≤ b | 2 ≤ i ≤ 4 | 空列の表現が醜い |
| a < i < b | 1 < i < 5 | 両端が不自然 |
「a ≤ i < b」の表記法では、部分列の長さが単純に「b - a」で求まる。さらに隣接する部分列を並べたとき、前の列の上限と次の列の下限が自然に一致する。この優雅さが、0-indexedの数学的根拠になっている。
1-indexedの言語はなぜ存在するのか
FortranやMATLABが1-indexedなのには正当な理由がある。これらの言語は数学者や科学者が主要ユーザーであり、数学の添え字表記(a₁, a₂, a₃...)と一致させることが最優先だった。
Luaが1-indexedを採用したのも興味深い。Luaはブラジルのリオデジャネイロ・カトリカ大学で生まれた言語で、プログラマーではなくエンジニアや地質学者が使うことを想定していた。彼らにとって「1番目の要素がインデックス1」であることは当然だった。
「Off-by-one error」——0-indexedが生む永遠のバグ
配列が0から始まることで、プログラマーは「Off-by-one error(OBOE)」という古典的なバグと永遠に戦い続けている。ループの終了条件を「<」にすべきか「<=」にすべきか——この判断ミスは、初心者からベテランまで等しく悩ませる。
あるセキュリティ研究では、CVE(共通脆弱性識別子)に登録されたバッファオーバーフローの約15%がOff-by-oneに起因するとされている。つまり0-indexedは効率を生む一方で、セキュリティリスクの源泉にもなっている。
「正しさ」と「わかりやすさ」のトレードオフ
SwiftやKotlinのような現代の言語でも、配列は0から始まる。ハードウェアの制約がほぼ消えた現代でも0-indexedが主流なのは、C言語から続く巨大なエコシステムとの互換性と、ダイクストラが示した数学的な整合性が支持されているからだ。
「なぜ0から始まるのか」という問いには、効率・歴史・数学・人間工学のすべてが交差している。次に配列を宣言するとき、あなたはその[0]に1960年代のメモリ管理の遺産を見るだろうか——それとも、ただ「最初の要素」と読むだろうか。