為何c語言的陣列索引是由0開始?
我們很難揣測 Ritchie 當年的心意,我的想法是:
當時一些可自訂陣列上下界的語言,如 Fortran,
在計算陣列元素位址時,需先扣去下界。
由於當時組合語言尋址範圍有限,最差情況可能只有
+-32768,當下界太大 (>32768) 或太小 (<-32768) 時,
下界無法在 Compiler time 靜態議決使之轉成 0 以加快元素存取速度,
只能每次存取時,實實在在的減去下界,這會拖慢存取速度。
於是,有 2 種解法:
(1) 設下語法限制,限定上下界範圍。
(2) 直接規定下界為 0。
選擇 (2) 可令陣列與指標間,具備合適的語法對應:
由於 C 中,「無索引標記的陣列名稱」會自動轉成
「指向陣列第一個元素的指標常數」,如:
short a[1];
單用 a 時,其值為 &a[下界],
亦為 &(*((a)+(下界))) 或 &(*((下界)+(a))),
令下界 = 0,則如下形式為等「值」:
a == &a[0] == &(*(a+0)) == &(*(0+a))
其中,deref (*) 與 addrof (&) 可相消解:
&(*(a+0)) == &*(a+0) == a+0 == a
又因 a == &a[0],消去 & 得:
*(a+0) == *a == a[0]
由於 *a 中的 a 視為「指向陣列第一個元素的指標常數」,
對其 dereference 必為「陣列第一個元素」,
而 *a 又相當於 *(a+0),為滿足 *(a+x) ~ a[x],
故令 x = 0。
當然,直接由 *(a+x) ~ a[x] 這個對應關係,
也可以推想出 x = 0 的合理性,但「含意」會比較少 :p
以「陣列指標」觀點來看 (pointer to array,
如:Type (*a)[n]) 則問題可簡化至指標。
由於我們允許,並限定: *(a+0) 等值於 *a
當 pointer 的 offset 起始值為 0 時,才能滿足此限定,
否則形成矛盾:*(a + low_boundary) == *a
沒有留言:
張貼留言