爲什麼很多編程語言中數組都是從0開始編號?

數組兩個特性

爲什麼很多編程語言中數組都是從 0 開始編號,首先先了解一下數組的概念。
數組 Array 是一種線性表數據結構,是一組連續的內存空間,用來存儲一組具有相同類型的數據。數組具備以下特性:

  • 線性表,是數據排列成像一條線一樣的結構,每個線性表上的數據最多隻有前和後兩個方向。比如,除了數組,還有鏈表、隊列和棧。

  • 連續的內存空間和相同類型的數據,正因爲這兩個特點,才讓數組的操作變得非常低效,要想在數組中刪除、插入一個數據,爲了保證連續性,就需要做大量的數據搬移工作。

正因爲這兩個特點,可以非常高效的通過下標進行隨機訪問

順序訪問和隨機訪問的區別

順序訪問:鏈表在內存中不是按順序存放的,而是通過指針連在一起,爲了訪問某一元素,必須從鏈頭開始順着指針才能找到某一個元素。

隨機訪問:數組在內存中是按順序存放的,可以通過下標直接定位到某一個元素存放的位置。

尋址公式

一維數組尋址公式:

a[k]_address = base_address + k * type_size

二維數組尋址公式:
假設二維數組大小爲 m*n,那麼尋址公式爲:

a[i][j]_address = base_address + (i * n + j) * type_size

三維數組尋址公式:
假設是 m*n*q,那麼尋址公式爲:

a[i][j][k]_address=base_address + (i * n * q + j * q + k) * type_size

其中, type_size 表示數組中每個元素的大小。

驗證

例如,聲明一個長度爲 10int 類型的數組。

int arr[10] = { 0 };
for (int i = 0; i < 10; i++) {
    arr[i] = i;
}

運行結果如下,

從運行結果可以看出,計算機給數組 arr,分配了 40 字節的內存,首地址爲 0x7ffeefbff4f0arr[0] 地址爲:0x7ffeefbff4f0arr[9] 地址爲:0x7ffeefbff514,每個 int4 個字節,故 arr[9] 結尾爲 0x7ffeefbff514

C 語言中數組名代表首地址,即第一個元素的地址,a[0] 就是偏移爲 0 的位置,a[k] 就表示偏移 k 個元素類型大小的位置。得出計算公式:

a[k]_address = base_address + k * type_size

結論

CPU 性能層面考慮:從數組存儲的內存模型上來看,“下標”最確切的定義應該是offset。前面也講到,如果用 a 來表示數組的首地址,a[0] 就是偏移爲 0 的位置即首地址,a[k] 就表示偏移 ktype_size 的位置。如果數組編號從 1 開始計數,那這個公式就會變爲:

a[k]_address = base_address + k * type_size
a[k]_address = base_address + (k-1) * type_size

對比兩個公式,如果從 1 開始編號,每次隨機訪問數組元素就多了一次減法運算,對於 CPU 來說就是多了一次減法指令,增加了性能開銷。

歷史原因層面考慮:C 語言設計者用 0 開始計數數組下標,之後的 JavaJavaScript 等高級語言都效仿了 C 語言,或者說,爲了在一定程度上減少 C 語言程序員學習 Java 的學習成本,因此繼續沿用了從 0 開始計數的習慣。實際上,很多語言中數組也並不是從 0 開始計數的,比如 Matlab。甚至還有一些語言支持負數下標,比如 Python

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章