国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
程序是用編程語言寫的,編譯器也是程序,先有編譯器還是編程語言

      

【【蝙蝠俠運(yùn)維開發(fā)】程序是用編程語言寫的,編譯器也是程序,先有編譯器還是編程語言】http://toutiao.com/group/6513455386396197383/?iid=15906422033&app=explore_article&timestamp=1516552928&tt_from=copy_link&utm_source=copy_link&utm_medium=toutiao_ios&utm_campaign=client_share 

             

我愛七龍珠

首先肯定的是先有的編程語言,哪怕這個(gè)語言簡單到只有一個(gè)符號(hào)。先是設(shè)計(jì)好語言的規(guī)則,然后編寫能夠識(shí)別這套規(guī)則的編譯器,否則若沒有語言規(guī)則做為指導(dǎo)方向,編譯器編寫將無從下筆。

第1個(gè)編譯器是怎么產(chǎn)生的,這個(gè)問題我并沒有求證,不過可以談下自己的理解,請(qǐng)大伙兒辯證地看。

這個(gè)問題屬于哲學(xué)中雞生蛋,蛋生雞的問題,這種思維回旋性質(zhì)的本源問題經(jīng)常讓人產(chǎn)生迷惑??墒乾F(xiàn)實(shí)生活中這樣的例子太多了,如:

1.英語老師教學(xué)生英語,學(xué)生成了英語老師后又可以教其他學(xué)生英語。

2.寫新的書需要參考其它舊書,新的書將來又會(huì)被更新的書參考,就像本書編寫過程一樣,要參考許多前輩的著作。

3.用工具可以制造工具,被制造出來的工具將來又可以制造新的工具。

4.編譯器可以編譯出新的編譯器。

這種自己創(chuàng)造自己的現(xiàn)象,稱為自舉。

自舉?是不是自己把自己舉起來?是的,人是不能把自己舉起來的,這個(gè)詞很形象的描述了這類“后果必須有前因”的現(xiàn)象。

以上前三個(gè)舉的都是生活例子,似乎比第4個(gè)更容易接受。即使這樣,對(duì)于前三個(gè)例子大家依然會(huì)有疑問:

1.第一個(gè)會(huì)英語的人是誰教的?

2.第一本書是怎樣產(chǎn)生的?

3.第一個(gè)工具是如何制造出來的?

其實(shí)看到第2個(gè)例子大家就可能明白了,世界上的第一本書,它的知識(shí)來源肯定是人的記憶,通過向個(gè)人或群眾打聽,把大家都認(rèn)同的知識(shí)記錄到某個(gè)介質(zhì)上,這樣第一本書就出生了。此后再記錄新的知識(shí)時(shí),由于有了這本書的參考,不需要重新再向眾人打聽了原有知識(shí)了,從此以后便形成了書生書的因果循環(huán)。

從書的例子可以證明,本源問題中的第一個(gè),都是由其它事物創(chuàng)建出來的,不是自己創(chuàng)造的自己。

就像先有雞還是先有蛋一樣,一定是先有的其它生命體,這個(gè)生命體不是今天所說的雞。伴隨這個(gè)生命體漫長的進(jìn)化中,突然有一天具備了生蛋的能力(也許這個(gè)蛋在最初并不能孵化成雞,這個(gè)生命體又經(jīng)過漫長的進(jìn)化,最終可以生出能夠孵化成雞的蛋),于是這個(gè)蛋可以生出雞了。過了很久之后,才有的人類。人一開始便接觸的便是現(xiàn)在的雞而不知道那個(gè)生命體的存在,所以人只知道雞是由蛋生出來的。

很容易讓人混淆的是編譯c語言時(shí),它先是被編譯成匯編代碼,再由匯編代碼編譯為機(jī)器碼,這樣很容易讓人誤以為一種語言是基于一種更底層的語言。

似乎沒有匯編語言,c語言就沒有辦法編譯一樣。拿gcc來說,其內(nèi)部確實(shí)要調(diào)用匯編器來完成匯編語言到機(jī)器碼的翻譯工作。因?yàn)橐呀?jīng)有了匯編語言編譯器,那何必浪費(fèi)這個(gè)資源不用,自己非要把c語言直接翻譯成機(jī)器碼呢,畢竟匯編器已經(jīng)無比健壯了,將c直接變成機(jī)器碼這個(gè)難度比將c語言翻譯為匯編語言大多了,這屬于重新造輪子的行為。

曾經(jīng)我就這樣問過自己,php解釋器是c語言寫的,c編譯器是匯編寫的(這句話不正確),匯編是誰寫的呢?后來才知到,編譯器gcc其實(shí)是用c語言寫的。咋一聽,什么?用c語言寫c編譯器?自己創(chuàng)造自己,就像電影超驗(yàn)駭客一樣。當(dāng)時(shí)的思維似乎陷入了死循環(huán)一樣,現(xiàn)在看來這不奇怪。其實(shí)編譯器用什么語言寫是無所謂的,關(guān)鍵是能編譯出指令就行了。編譯出的可執(zhí)行文件是要寫到磁盤上的,理論上,只要某個(gè)進(jìn)程,無論其是不是編譯器,只要其關(guān)于讀寫文件的功能足夠強(qiáng)大,可以往磁盤上寫任意內(nèi)容,都可以生成可執(zhí)行文件,直接讓操作系統(tǒng)加載運(yùn)行。相像一下,用python寫一個(gè)腳本,功能是復(fù)制一個(gè)二進(jìn)制可執(zhí)行文件,新復(fù)制出來的文件肯定是可以執(zhí)行的。那python腳本直接輸出這樣的一個(gè)二進(jìn)制可執(zhí)行文件,它自然就是可以直接執(zhí)行的,完全脫離python解釋器了。

編譯器其實(shí)就是語言,因?yàn)榫幾g器在設(shè)計(jì)之初就是先要規(guī)劃好某種語言,根據(jù)這個(gè)語言規(guī)則來寫合適的編譯器。所以說,要發(fā)明一種語言,關(guān)鍵是得寫出與之配套的編譯器,這兩者是同時(shí)出來的。最初的編譯器肯定是簡單粗糙的,因?yàn)楫?dāng)時(shí)的編程語言肯定不完善,頂多是幾個(gè)符號(hào)而已,所以難以稱之為語言。只有功能完善且符合規(guī)范,有自己一套體系后才能稱之為語言。不用說,這個(gè)最初的編譯器肯定無法編譯今天的c語言代碼。編程語言只是文本,文本只是用來看的,沒有執(zhí)行能力。最初的編譯器肯定是用機(jī)器碼寫出來的。這個(gè)編譯器能識(shí)別文本,可以處理一些符號(hào)關(guān)鍵字。隨著符號(hào)的越來越多,不斷地去改進(jìn)這個(gè)編譯器就是了。

以上的符號(hào)說的就是編程語言。后來這個(gè)編譯器支持的關(guān)鍵字越來越多了,也就是這個(gè)編譯器支持的編程語言越發(fā)強(qiáng)大了,可以寫出一些復(fù)雜的功能的時(shí)候,干脆直接用這個(gè)語言寫個(gè)新的編譯器,這個(gè)新的編譯器出生時(shí),還是需要用老的編譯器編譯出來的。只要有了新的編譯器,之后就可以和老的編譯器說拜拜了。發(fā)明新的編譯器實(shí)際上就是能夠處理更多的符號(hào)關(guān)鍵字,也就是又有新的開發(fā)語言了,這個(gè)語言可以是全新的也可以是最初的語言,這取決于編譯器的實(shí)現(xiàn)。這個(gè)過程不斷持續(xù),不斷進(jìn)化,逐漸才有了今天的各種語言解釋器,這是個(gè)迭代的過程。

這張圖片在網(wǎng)絡(luò)上非?;?,它常常與勵(lì)志類的文字相關(guān)。起初看到這個(gè)雕像在雕刻自己時(shí),我著實(shí)被感動(dòng)了,感受到的是一種成長之痛。今天把它貼過來的目的是想告訴大家,起初的編譯器也是功能簡單,不成規(guī)范,然而經(jīng)過不斷自我“雕刻”,它才有了今天功能的完善。

下面的內(nèi)容是我參考了別人的文章,由于找不到這位大師的署名,只好在此先獻(xiàn)上我真摯的敬意,感謝他對(duì)求知者的奉獻(xiàn)。

要說到C編譯器的發(fā)展,必須要提到這兩位大神——C語言之父Dennis Ritchie和Ken Thompson。Dennis和Ken在編程語言和操作系統(tǒng)的深遠(yuǎn)貢獻(xiàn)讓他們獲得了計(jì)算機(jī)科學(xué)的最高榮譽(yù),Dennis和Ken于1983年贏得了ACM圖靈獎(jiǎng)。

編譯器是靠不斷學(xué)習(xí),不斷積累才發(fā)展起來的,這是自我學(xué)習(xí)的過程,下面來看看他們是如何讓編譯器長大的。

我們都知道轉(zhuǎn)義字符,轉(zhuǎn)義字符是以’\’開頭的多個(gè)字符,通常表示某些控制字符,它們通常是不可鍵入的,也就是這些字符無法在鍵盤上直接輸入,比如’\n’表示回車換行,’\t’表示tab。由于以’\’開頭的字符表示轉(zhuǎn)義,因此要想表示’\’字符本身,就約定用’\’來轉(zhuǎn)義自己,即’\\’表示字符’\’。轉(zhuǎn)義字符雖然表示的是單個(gè)字符的意義,在編譯器眼里轉(zhuǎn)義字符是多個(gè)字符組成的字符串,比如’\n’是字符’\’和’n’組成的字符串,好啦,交待完畢。

起初的c編譯器中并沒有處理轉(zhuǎn)義字符,為敘述方便,我們現(xiàn)在稱之為老編譯器。如果待編譯的代碼文件中有字符串’\\’,這在老編譯器眼里就是’\\’字符串,并不是轉(zhuǎn)義后的單個(gè)字符’\’。為了表明編譯器與做為其輸入的代碼文件的關(guān)系,我們稱做為輸入的代碼文件為應(yīng)用程序文件,盡管被編譯的代碼文件是實(shí)現(xiàn)了一個(gè)編譯器,而在編譯器眼里,它只是一個(gè)應(yīng)用程序級(jí)的角色。例如,gcc –c a.c中,a.c就是應(yīng)用程序文件。

現(xiàn)在想在編譯器中添加對(duì)轉(zhuǎn)義字符的支持,那就需要修改老編譯器的源代碼,假設(shè)老編譯器的源代碼文件名為compile_old.c。被修改后的編譯器代碼,已不屬于老編譯器的源代碼,故我們命名其文件名為compile_new_a.c,下面是修改后的內(nèi)容。

代碼compile_new_a.c

其中,函數(shù)next()的功能是返回待處理文本(即被編譯的源碼文件)中的下一字符,強(qiáng)調(diào)一下是單個(gè)字符,并不是記法分析中的單詞(即token)。

用老編譯器將新編譯器的源代碼compile_new_a.c編譯,生成可執(zhí)行文件,該文件就是新的編譯器,我們?nèi)∶麨樾戮幾g器_a。為了方便理清他們的關(guān)系,將他們列入表格中。

編譯器自身源代碼編譯器應(yīng)用程序源代碼輸出文件名
compile_old.c老編譯器compile_new_a.c新編譯器_a,支持’\\’

這下編譯出來的新編譯器_a可以編譯含有轉(zhuǎn)義字符’\\’的應(yīng)用程序代碼了,也就是說,待編譯的文件(也就是應(yīng)用程序代碼)中,應(yīng)該用’\\’來表示’\’。而單獨(dú)的字符’\’在新編譯器_a中未做處理而無法通過編譯。所以此時(shí)新編譯器_a是無法編譯自己的源代碼compile_new_a.c的,因?yàn)樵撛次募兄皇菃蝹€(gè)’\’字符,新編譯器_a只認(rèn)得’\\’。

先更新他們的關(guān)系,見下表。

編譯器自身源代碼編譯器應(yīng)用程序源代碼輸出文件名
compile_old.c老編譯器compile_new_a.c新編譯器_a,支持’\\’
compile_new_a.c新編譯器_acompile_new_a.c編譯失敗

也就是說,現(xiàn)在新編譯器_a,無法編譯自己的源文件compile_new_a.c,只有老編譯器才能編譯它。再啰嗦一下,新編譯器_a無法正確編譯自己的源文件compile_new_a.c的原因是,compile_new_a.c中’\’字符應(yīng)該用轉(zhuǎn)義字符的方式來引用,即所有用’\’的地方都應(yīng)該替換為’\\’。再回頭看一下新編譯器_a的源代碼compile_new_a.c,它只處理了字符串’\\’,單個(gè)’\’沒有對(duì)應(yīng)的處理邏輯。下面修改代碼,將新修改后的代碼命名為compile_new_b.c。

代碼 compile_new_b.c

其實(shí)compile_new_b.c只是更新了轉(zhuǎn)義字符的語法,這是新編譯器_a所支持的新的語法,下面還是以新編譯器_a來編譯新的編譯器。

用新編譯器_a編譯此文件,將生成新編譯器_b,將新的關(guān)系錄入到表格中。

編譯器自身源代碼編譯器應(yīng)用程序源代碼輸出文件名
compile_old.c老編譯器compile_new_a.c新編譯器_a,支持’\\’
compile_new_a.c新編譯器_acompile_new_a.c編譯失敗
compile_new_a.c新編譯器_acompile_new_b.c新編譯器_b,支持’\\’

繼續(xù)之前啰嗦兩句:用編譯器去編譯另一編譯器的源碼,也許有的同學(xué)覺得很費(fèi)解,其實(shí)您把被編譯的編譯器源碼當(dāng)成普通的應(yīng)用程序源碼就特別容易理解了。上面的編譯器代碼compile_new_b.c,其第3、6、7行的字符串’\\’被新編譯器_a處理后,會(huì)以單字符’\’來代替(這是新編譯器_a源碼中return語句的功能),因此最終處理完成后的代碼等同于代碼compile_new_a.c。

現(xiàn)在想加上換行符’\n’的支持:

由于現(xiàn)在編譯器還不認(rèn)識(shí)’\n’,故這樣做肯定不行,不過可以用其ascii碼來代替,將其命名為compile_new_c.c。

compile_new_c.c

用新編譯器_a來編譯compile_new_c.c,將生成新編譯器_c,新編譯器_c的代碼相當(dāng)于代碼compile_new_c.c中所有’\\’被替換為’\’后的樣子,如下所示,暫且稱之為代碼compile_new_c1.c:

代碼compile_new_c1.c

編譯器自身源代碼編譯器應(yīng)用程序源代碼輸出文件名
compile_old.c老編譯器compile_new_a.c新編譯器_a,支持’\\’
compile_new_a.c新編譯器_acompile_new_a.c編譯失敗
compile_new_a.c新編譯器_acompile_new_b.c新編譯器_b,支持’\\’
compile_new_a.c新編譯器_acompile_new_c.c新編譯器_c,間接支持\n

最后再修改compile_new_c.c為compile_new_d.c,將10用’\n’替代。

代碼compile_new_d.c

用新編譯器_c編譯compile_new_d.c,生成新編譯器d,將直接識(shí)別’\n’。同理,新編譯器d的代碼相當(dāng)于代碼compile_new_d.c中,所有字符串’\\’被替換為字符’\’、字符’\n’被替換為數(shù)字10后的樣子,即等同于代碼compile_new_c1.c。

編譯器自身源代碼編譯器應(yīng)用程序源代碼輸出文件名
compile_old.c老編譯器compile_new_a.c新編譯器_a,支持’\\’
compile_new_a.c新編譯器_acompile_new_a.c編譯失敗
compile_new_a.c新編譯器_acompile_new_b.c新編譯器_b,支持’\\’
compile_new_a.c新編譯器_acompile_new_c.c新編譯器_c,間接支持\n
compile_new_c.c新編譯器_ccompile_new_d.c新編譯器d,直接支持\n

編譯器經(jīng)過這樣不斷的訓(xùn)練,功能越來越強(qiáng)大,不過體積也越來越大了。

累死哥了。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
為什么自制腳本語言是編程語言的最高境界?
先有雞還是先有蛋?C 編譯器是用什么語言編的?
用“Whitespace”編程語言編寫無字天書
1.1 什么是編程語言
DSP編程技巧:揭開編譯器神秘面紗之程序優(yōu)化
【C語言筆記】ASCII碼可見字符與不可見字符
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服