為什麼計算機語言中的變數名都不能以數字開頭呢?


如果以數字開頭,這個變數就可能是純數字了,這樣語言的編譯器(或解釋器)就分不清當前的是數字還是變數名了。即使不是純數字,如100000L在有些語言中表示長整型,還是會有歧義的。


簡單地說,如果允許變數名以數字開頭,那麼形如「1e5」,「100L」,「10f」這樣的,應該識別為數字還是變數名呢?


主要是工程折衷。

程序語言的分析分詞法和語法兩部分。詞法分析主要用的是正規文法,也就是三型文法。這類文法主要採用正則表達式分析。正則文法分析器的特點是它是不回溯的,所以實現很簡單。

如果一個變數以數字開頭,那麼分析器就必須在遇到第一個或第二個英文字元的時候回溯來確定是否是數字、變數名還是詞法錯誤,這時候就變成了二型文法。二型文法分析器的好處是支持回溯和遞歸語法(所以語法分析是靠它的),但是缺點是狀態機相比正則文法狀態大大增加,而且代碼寫起來更困難。

考慮到詞法分析部分只是用來斷字,我們實在是沒有為了支持變數名以數字開頭這麼一個小功能而讓整個詞法分析部分用二型文法寫。

故,最後大家都默認了變數要避免用數字開頭。


如7樓所說的,其實有些語言的變數名是可以用數字開頭的,只是不能完全是數字,如1a在C語言當中就是非法的,但是在Common Lisp裡面就是可用的~


最近剛好在上編譯原理,應該算是詞法分析的問題。因為每次輸入「頭符號」後要判斷該符號是數字還是字元,如果是數字,則可以直接跳入數字處理的模塊,若是字元則按變數名來處理。如果允許變數名以數字開頭,則以後每次輸入一個符號都要做一次「是否為數字」的判斷,直到符號出現非數字再轉成變數名,而禁止以數字開頭只需要判斷一次,很顯然「每一次都要判斷」是一種極大的浪費。另外變數名以數字開頭對程序員而言也沒有任何的幫助,反而降低了編譯器的性能,畢竟O(1)和O(n)還是差距不小的。

這是我自己做完編譯原理詞法分析實驗後的一些看法,水平有限,希望各位指正。


票數最多的幾位所說的詞法解析器複雜性的問題是有道理的。我想補充的是允許變數以數字開頭的語言也是有的,比如Scheme的很多實現中就有1+這個函數,(1+ a)等價於C中的++a。


var 1e6 = 1e6...這樣的變數名讓compiler情何以堪


葉曉斌的答案是對的,排名第一那個答案是錯的,這玩意跟上下文無關文法沒有任何關係,也不需要回溯。

詞法分析基本上分三步,第一步把詞法單元分割出來,第二步判斷詞性,是數字,是普通變數,是關鍵字,還是是類型變數...第三步確定其符合本詞性所限定的語法規則,然後進行下一步的處理

如果第一個字元就能判斷詞性的話,接下來就是把這個詞交給相應詞性的正則表達式匹配器來判斷是否通過

如果數字能做普通變數的開頭,那麼就要先匹配數字,直到遇到特定字元串再分配給普通變數的正則表達式匹配器來判斷是否通過

這樣對分析器的效率只有很小的影響。實際上關鍵字和普通變數的正則表達式就是重合的,比如c語言的while,當分析器讀到e的時候也不能確定它是一個關鍵字還是普通變數

所以現代語言做出這種決定更多是從人的閱讀習慣和簡化詞法分析器結構出發


1.主要還是習慣,數學變數通常是x_1, x_2,下標都寫在右側,計算機語言沿襲這一些管是很正常的事情;

2.詞法解析一般是從左到右的,10000L遇到L可以很自然作為一個終結符,但如果允許1000Lesbian,那麼L就沒辦法作為終結符,需要從e開始判斷。這樣需要記住一個像L這樣的位元組作為Buffer,判斷起來就不是很簡潔。


在《javascript權威指南》上剛好看到了一句:

P26.數字不允許作為首字元出現,這樣javascript就可以輕易的區別開標識符和數字了;

或許能這樣解釋 :)


開始的詞法分析很多是手寫的(今天也有很多是手寫詞法分析),這種情況下,能簡單就簡單,允許數字打頭的標識符可以認為是不必要的麻煩,並不能帶來什麼好處。


這更多是為避免二義性,更少是為了簡化Lexer的考慮。

還是看 SO 的討論吧 http://stackoverflow.com/questions/342152 。


除了樓上們說的,還有一個原因是:即便允許數字開頭,那也必需再加一句:「但不能只包含數字。」


在不降低可用性的前提下,簡化詞法分析器的實現,避免不必要的複雜性。


就好像不少網站都不準使用純數字作為用戶名(變數名)一樣,為了和用戶ID(數值)區分開來……


我記得Tcl語言可以用純數字做變數名啊?


雖然是舊問題,我還是翻出來,因為多贊的那個解釋確實誤導人,這完全在正則表達式能力裡面,理由在那帖評論里已經足夠

編程規範里會強調,避免直接用數字,

比如說

limit = 4294967295

也會建議寫成

const int MAX_INT = 4294967295

......

limit = MAX_INT

何況是變數名,

而且肉眼也容易將數字開頭的變數名理解成值,

所以這只是一個語言設計問題,


如果以數字開頭,16進位與變數就出現混淆了,如0x10, 0xFF


如樓上所言,容易產生歧義,除了 1000000L 之外,還有 102h 表示 hex 等。


這是考慮計算機沒那麼智能的識別關鍵字,編譯器的詞法分析器的分析能力也是有限的


如果可以用數字作為變數名,那麼

會出現 int 1 = 2; if (1 == 2) {...}

這種代碼,讓計算機情何以堪?

如果可以用數字作為一個變數名的開頭,但後面必須跟字母,這還不如規定不能以數字開頭來得簡潔。


有一部分原因在於避免歧義..

還有很大一部分在於可讀性吧..

至於編譯器的複雜性..我覺得這個可以忽略..CL也支持數字開頭的變數名..也沒感覺有什麼複雜的..

關鍵還是一個名字給閱讀/編寫代碼人的一個舒適感..

就好象一些我們約定俗成的編碼規範一樣..


推薦閱讀:

對於程序員來說,哪些網站代碼比較多比較全,問題解決比較快?
go有哪些快速開發的web框架?
在軟體開發中,追求新的技術意義大嗎?
尾遞歸究竟是好是壞?
Google MapReduce中的map和reduce與函數式編程中的map,reduce有何異同?

TAG:編程 | 編譯原理 | 編譯器 |