為什麼有些程式語言的陣列要從零開始算?

時間 2021-05-31 04:53:43

1樓:周娛娛雨御與漁

非要問有什麼優勢的話,我給你分享一點思路。

陣列(Array)是一種線性表資料結構,它用一組連續的記憶體空間,來儲存一組具有相同型別的資料。

因為陣列的儲存結構是一組連續的記憶體空間,所以陣列具有「快速查詢」的特性,支援隨機訪問

陣列根據首位址和下標,實現對元素記憶體的隨機訪問。

定址公式:

a[i]_address = base_address + i * data_type_size

現在回答樓主的問題:

從陣列儲存的記憶體模型上來看,「下標」最確切的定義應該是「偏移」,如果用 a 來表示陣列的首位址,a[0] 就是偏移為 0 的位置,也就是首位址,a[k] 就表示偏移 k 個 type_size 的位置,所以計算 a[k] 的記憶體位址只需要用這個公式:

a[k]_address = base_address + k * type_size

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

對比兩個公式,我們不難發現,從 1 開始編號,每次隨機訪問陣列元素都多了一次減法運算,對於 CPU 來說,就是多了一次減法指令。

非要說陣列下標從零開始計數,有什麼優勢的話,這應該算乙個吧。

2樓:龍騰道默默地

在字串擷取函式中這個問題會得到直觀的理解。第乙個字,第二個字,第三個字——下標數字應該理解成那個逗號分割位置的編號,而不是位置本身的編號。否則你說1是第乙個字的左邊還是右邊?

不喜歡記憶體這種底層+歷史原因,因為那並不能解釋為什麼後來不改掉。

3樓:myd7349

今天看到《Algorithms》1.1 中的乙個 Q&A:

Q.Why do array indices start at 0 instead of 1?

A.This convention originated with machine-language programming, where the address of an array element would be computed by adding the index to the address of the

beginning of an array. Starting indices at 1 would entail either a waste of space at the

beginning of the array or a waste of time to subtract the 1.

----

4樓:

這個和陣列訪問的方式有關,陣列是存在記憶體裡的,如何訪問乙個記憶體,只需要拿到這個記憶體的位址就可以了。

但是如何拿到第i個元素的位址呢,拿到陣列的首位址,加上相對偏移就能計算出第i個元素的位址,這個偏移比較好算,因為每個元素的大小都是一樣的,就用元素大小乘以元素個數就能獲得偏移量了。

陣列記憶體結構就是連續排列的很多記憶體塊。則可知:

第1個元素的位址=首位址a

第2個元素的位址=首位址a + 1*元素大小第3個元素的位址=首位址a + 2*元素大小第4個元素的位址=首位址a + 3*元素大小第5個元素的位址=首位址a + 4*元素大小第i個元素的位址=首位址a + (i-1)*元素大小所以如果用1來做元素第乙個編號在計算記憶體位址的時候總會進行一次減法,用0就不會,所以用違背常規的方法換來了計算速度。

用反彙編也可以得到證實。

5樓:Milo Yip

我提一些這裡暫時沒有提到的。

下標通常用無號整數表示。乙個n位無號整數的表示範圍是。如果下標由1開始,意味著只能有2^n-1個下標可以使用。

現代用32-bit/64-bit做下標可能不覺得是大問題,但在用8-bit/16-bit做下標的時候就是比較大的問題。

可對下標採用同餘算術(Modular arithmetic)。

6樓:

我是跟著來搞笑的。

換我這種渣渣寫c語言的編譯器的話,我絕對願意將陣列定為0開始,位址計算方便多了,編譯器好寫多了,反正是c語言這麼接近彙編的東西是吧……所以不妨我們為了方便就這麼規定了吧,哼,才不是因為懶呢!

7樓:

這個問題,Dijkstra 大神在 1982 年就寫過一篇小文章了,題為 Why numbering should start at zero

總共也就 3 頁手寫,我就摘重點的大致翻譯一下:

為了表示乙個自然數序列 2, 3, …, 12,排除掉中間的那三個點 (...),總共有四種方式可供我們選擇:

a) 2 <= i < 13

b) 1 < i <= 12

c) 2 <= i <= 12

d) 1 < i < 13

有沒有什麼原因使得我們應該選其中的某一種而不是其他的呢?是的,的確有。觀察到 a) 和 b) 的優勢是不等式的上下界之差恰好是序列的長度。

基於此,作為乙個中間結論:在 a) 和 b) 兩種表達中中,兩個序列是鄰接的就意味著乙個的上界等於另外乙個的下界。但這些考量並沒有讓我們從 a) 和 b) 之中做出選擇,所以我們從頭開始。

存在乙個最小的自然數。排除掉下界——就像 b) 和 d) 中那樣——就會使得乙個從最小的自然數開始的序列的下界變成非自然數。這樣的表達方式很難看,所以對於下界應該更傾向於 <=,就像 a) 和 c) 那樣。

現在,考慮一下從最小的自然數開始的序列:假如包含上界,當序列縮小成空序列時,就會使得 c) 不那麼像自然數集。這樣的表達方式也很難看,所以對於上界應該更傾向於 <,就像 a) 和 d) 那樣。

綜上所述, 我們應該傾向於使用 a) 的表達方式。

當處理長度為 N 的序列時,我們期望通過下標來區分它的元素。下乙個惱人的問題就是,我們該給它的第乙個元素賦予什麼下標值?使用 a) 的表達方式,當下標從 1 開始時,下標範圍為 1 <= i < N+1;當下標從 0 開始時則是 0 <= i < N,更好看。

所以,讓我們將序號從 0 開始:乙個元素的序號(下標)等於序列中在它前面的元素個數。這個故事的寓意是我們更應該——過了這麼多個世紀!

——把 0 當作乙個自然數。

8樓:張李

從哪個開始算不一回事情自然數都是從1開始算得說白了從0開始算不過是為了指標使用方便因為arr(0)得位址和arr位址一樣如果 arr +1 就是第二個元素了? 簡單說比arr位址多1得位址代表第二個變數,這樣更符合邏輯?

9樓:勞里林

其實無所謂從0或1開始,都是習慣

陣列的下標應該是從0還是從1開始?我提議的妥協方案是0.5,可惜他們未予認真考慮便一口回絕。—— Stan Kelly-Bootle

10樓:Kenneth

不從零開始的才是逗逼。

不從零開始的設計初衷可能是為了讓人感覺自然,貼近自然人的習慣。但是在大多數語言都從0開始計算下標的時候,不從0開始的反而不自然了。

從效率上來說,從0開始是效率最高的,下標數直接就是儲存位置的偏移量;從1開始還得下標減1才是偏移量,效能差異雖然微乎其微,但終究不是最直接的方式。

為什麼程式語言列表索引從零開始

好名真難取 因為陣列最開始是C語言裡的 C語言裡的陣列最後都會被編譯器轉換成指標而訪問陣列的方式就是指標指向的記憶體位址 資料型別大小 偏移量而索引就是偏移量 C 語言裡陣列的首位址是 a,第二項位址是 a 1,之後是 a n,於是 a n 就有了乙個語法糖 a n 或 n a 而 a 0 也就是 ...

為什麼有些程式語言的型別推斷可以推斷函式引數,有些不會,哪種更好?

clears Pan 強答加不請自來。js應該是很極端的例子了吧,他允許程式設計師不宣告所有變數的型別,全是編譯器自己推斷。結果是 執行同樣的演算法js幾乎是最慢的。問題是 js本身在前端,很多時候並不需要太複雜的演算法,基本只根據使用者的輸入進行相應的反饋。所以即使慢一點,也在使用者可接受範圍內,...

為什麼大多數程式語言中陣列的第乙個元素的索引不從 1 開始?

漁父 因為對模運算太不友好了,什麼事都得想著 1,Matlab 用的我想死,結果 Julia 還這麼設計。autoi k quarter auto result complex t 這個 C 怎麼翻譯成 Matlab Julia k 是個模 quarter 的週期變數,quarter i 是 qua...