本博客已經(jīng)遷移至:本文通過匯總一些網(wǎng)上搜集到的資料,總結(jié)出大部分編程語言中數(shù)組下標(biāo)從0開始的原因
http://cenalulu.github.io/
本篇博文已經(jīng)遷移,閱讀全文請(qǐng)點(diǎn)擊:http://cenalulu.github.io/linux/why-array-start-from-zero/
我們知道大部分編程語言中的數(shù)組都是從0開始編號(hào)的,即array[0]
是數(shù)組的第一個(gè)元素。這個(gè)和我們平時(shí)生活中從1開始編號(hào)的習(xí)慣相比顯得很反人類。那么究竟是什么樣的原因讓大部分編程語言數(shù)組都遵從了這個(gè)神奇的習(xí)慣呢?本文最初是受stackoverflow上的一個(gè)問題的啟發(fā),通過搜集和閱讀了一些資料在這里做個(gè)總結(jié)。當(dāng)然,本文摘錄較多的過程結(jié)論,如果你想把這篇文章當(dāng)做快餐享用的話,可以直接跳到文章末尾看結(jié)論。
在回答大部分我們無法解釋的詭異問題時(shí),我們最常用的辯詞通常是歷史原因
。那么,歷史又是出于什么原因,使用了0標(biāo)號(hào)數(shù)組呢?Mike Hoye就是本著這么一種追根刨地的科學(xué)精神為我們找到了解答。以下是一些他的重要結(jié)論的摘錄翻譯:
據(jù)作者的說法,C語言中從0開始標(biāo)號(hào)的做法是沿用了BCPL這門編程語言的做法。而BCPL中如果一個(gè)變量是指針的話,那么該指針可以指向一系列連續(xù)的相同類型的數(shù)值。那么p+0
就代表了這一串?dāng)?shù)值的第一個(gè)。在BCPL中數(shù)組第5個(gè)元素的寫法是p!5
,而C語言中把寫法改成了p[5]
,也就是現(xiàn)在的數(shù)組。具體原文摘錄如下:
If a BCPL variable rePResents a pointer, it points to one or more consecutive Words of memory. These words are the same size as BCPL variables. Just as machine code allows address arithmetic so does BCPL, so if p is a pointer p+1 is a pointer to the next word after the one p points to. Naturally p+0 has the same value as p. The monodic indirection Operator ! takes a pointer as it’s argument and returns the contents of the word pointed to. If v is a pointer !(v+I) will access the word pointed to by v+I.
至于為什么C語言中為什么使用[]
方括號(hào)來表示數(shù)組下標(biāo),這個(gè)設(shè)計(jì)也有一定來歷。據(jù)C語言作者的說法是方括號(hào)是現(xiàn)代鍵盤上唯一較為容易輸入的成對(duì)符號(hào)(不用shift
)不信你對(duì)著鍵盤找找?
根據(jù)Mike的說法,BCPL是被設(shè)計(jì)在IBM硬件環(huán)境下編譯運(yùn)行的。在1960后的很長(zhǎng)一段時(shí)間內(nèi),服務(wù)器硬件幾乎被IBM統(tǒng)治。一個(gè)城市內(nèi)也許至于一臺(tái)超級(jí)計(jì)算機(jī),還需要根據(jù)時(shí)間配額使用。當(dāng)你當(dāng)天的配額用完以后,你的程序就被完全清出計(jì)算隊(duì)列。甚至連計(jì)算結(jié)果都不給你保留,死無全尸。這個(gè)時(shí)候?qū)懸欢胃咝У某绦?,就顯得比什么都重要了。而這時(shí)0下標(biāo)數(shù)組又體現(xiàn)了出了它的另一個(gè)優(yōu)勢(shì),就是:相較于1下標(biāo)數(shù)組,它的編譯效率更高。原文摘錄如下:
So: the technical reason we started counting arrays at zero is that in the mid-1960’s, you could shave a few cycles off of a program’s compilation time on an IBM 7094. The social reason is that we had to save every cycle we could, because if the job didn’t finish fast it might not finish at all and you never know when you’re getting bumped off the hardware because the President of IBM just called and fuck your thesis, it’s yacht-racing time.
此外,還有另外一種說法。在C語言中有指針的概念,而指針數(shù)組標(biāo)號(hào)實(shí)際上是一個(gè)偏移量而不是計(jì)數(shù)作用。例如對(duì)于指針p
,第N個(gè)元素是*(p+N)
,指針指向數(shù)組的第一個(gè)元素就是*(p+0)
,
上文中提到的為了計(jì)較分秒的編譯時(shí)間而使用0下標(biāo)數(shù)組,在硬件飛速發(fā)展的今天顯然是不必要的。那么為什么一些新興語言,如Python依然選擇以0作為數(shù)組第一個(gè)元素呢?難道也是歷史原因
?對(duì)于這個(gè)問題,Python的作者Guido van Rossum也有自己的答案。這里大致概括一下作者的用意:從0開始的半開放數(shù)組寫法在表示子數(shù)組(或者子串)的時(shí)候格外的便捷。例如:a[0:n]
表示了a中前n個(gè)元素組成的新數(shù)組。如果我們使用1開始的數(shù)組寫法,那么就要寫成a[1:n+1]
。這樣就顯得不是很優(yōu)雅。那么問題來了,Python數(shù)組為什么使用半開放,即[m,n)
左閉合右開發(fā)的寫法呢?這個(gè)理解起來就比較簡(jiǎn)單,讀者可以參考http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF作為擴(kuò)展閱讀。下面摘錄一段Python作者的原話:
Using 0-based indexing, half-open intervals, and suitable defaults (as Python ended up having), they are beautiful:
a[:n]
anda[i:i+n]
; the former is long fora[0:n]
.Using 1-based indexing, if you wanta[:n]
to mean the first n elements, you either have to use closed intervals or you can use a slice notation that uses start and length as the slice parameters. Using half-open intervals just isn't very elegant when combined with 1-based indexing. Using closed intervals, you'd have to writea[i:i+n-1]
for the n items starting at i. So perhaps using the slice length would be more elegant with 1-based indexing? Then you could writea[i:n]
. And this is in fact what ABC did -- it used a different notation so you could writea@i|n
.(See http://homepages.cwi.nl/~steven/abc/qr.html#EXPRESSIONS.)
從0標(biāo)號(hào)的數(shù)組傳統(tǒng),沿用了這么長(zhǎng)時(shí)間的原因主要列舉如下:
新聞熱點(diǎn)
疑難解答
圖片精選