配列の最初の要素がary[0]に格納されたりsubstring()関数の起点がゼロであったりしますが
ゼロでなく1ではダメなのでしょうか。個人的にはary[1]ary[2]ary[3]の方が1番目がary[1]という感じでわかりやすいのですが、ゼロから始まる利点が知りたいです
言語としては、0始まりでも1始まりでも整合性がとれなくなることはないので、どちらでもいいのです。
現に、BASIC系の言語ではOPTION BASE命令という命令があって、これは配列を0始まりにするか1始まりにするか設定するためのものです。
では、JavascriptなりPHPなりのC系の言語ではなぜ配列の底が0に固定されているのか?
これは、Cの実装の問題に行き着きます。
Cでは、配列というものを「連続したメモリ空間の、先頭アドレス」で表現していました。
そのメモリ空間の、最初の要素のアドレスは?
「先頭アドレス+0」ですね。2番目の要素のアドレスは「先頭アドレス+1(*その変数型のバイトサイズ)」です。
底が0にしておけばメモリアドレス計算がシンプルになる、というのがCでの事情です。
JavascriptやPHPなど、Cの文法を借用しただけのスクリプト言語にも同じ事情が存在するとは考えにくいです。もっと複雑な配列管理をしているはずなので。
しかし、文法を引き継いだ関係上、「0でも1でもどちらでもいい」配列の底については、Cの0をそのまま引き継いだのでしょう。
言語としては、0始まりでも1始まりでも整合性がとれなくなることはないので、どちらでもいいのです。
現に、BASIC系の言語ではOPTION BASE命令という命令があって、これは配列を0始まりにするか1始まりにするか設定するためのものです。
では、JavascriptなりPHPなりのC系の言語ではなぜ配列の底が0に固定されているのか?
これは、Cの実装の問題に行き着きます。
Cでは、配列というものを「連続したメモリ空間の、先頭アドレス」で表現していました。
そのメモリ空間の、最初の要素のアドレスは?
「先頭アドレス+0」ですね。2番目の要素のアドレスは「先頭アドレス+1(*その変数型のバイトサイズ)」です。
底が0にしておけばメモリアドレス計算がシンプルになる、というのがCでの事情です。
JavascriptやPHPなど、Cの文法を借用しただけのスクリプト言語にも同じ事情が存在するとは考えにくいです。もっと複雑な配列管理をしているはずなので。
しかし、文法を引き継いだ関係上、「0でも1でもどちらでもいい」配列の底については、Cの0をそのまま引き継いだのでしょう。
なるほどわかりやすい回答ありがとうございます。
いつも釈然としない気持ちで作業していたのですっきりしました。
C言語の配列とポインタを学べば0起点になっている理由がわかると思います。
配列は先頭のポインタが指すアドレスと、オフセットという形になっています。
配列の先頭のアドレス=ポインタのアドレス、すなわちオフセット0なので0番目とみなすほうが都合がいいわけです。
C言語は長年広く使われている言語なので他の言語もそれに追随していると思います。
プログラミング言語においては、インデックスは0番目から数える文化です。
1起点の言語もあります。たとえばBASICなどの言語では1起点です。
Perlは変態で「$[」というグローバル変数で起点を変更できます。
ゼロ起点があまり感覚的になじまないのでPHPでも起点を変更できたらいいのにな、と思ってしまいました。回答ありがとうございます
既に完璧な回答がついてるようですが、例えばプログラムを全く知らない人に説明するとしたら、こう説明します。
「年齢だって、生まれたとき0歳から始まるでしょ?0歳からはじめると、年齢=生きてきた年数になって分かりやすいよねー。」
たしかに年齢で考えれば「=生きてきた年数」となってわかりやすい気がしますが、それをプログラムのゼロ起点に当てはめると「生きてきた年数」に相当するものがいまいちピンと来ないです。
「N番目」を「インデックスがN」という表現に置き換えてみるとすっきりすると思います。
「インデックスがN」というのは無意識に頭の中でやっているかもしれません‥。
この質問をしたときは回答者の方々に「1から始まったら困ることがこんだけあるんだぞ」と言われるのを覚悟(というか期待)
していたのですが考察を読んで「ゼロ起点キモチ悪い」(=私)の考え方も変じゃないんだなと安心しました。
なるほどわかりやすい回答ありがとうございます。
いつも釈然としない気持ちで作業していたのですっきりしました。