2009年10月31日 星期六

陣列下界

 
為何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

沒有留言:

張貼留言