?? 初學編程之必備內(nèi)功.txt
字號:
初學編程之必備內(nèi)功(上)
1.程序是什么?
簡言之,程序是用來描述、指導計算機完成我們需要完成的任務(wù)的代碼(廣義的程序還包括相關(guān)的軟件運行所需的圖片、動畫、聲音等資源)。比如,我要向屏幕打印一個字母“A”;或者要讓CPU為我計算2+3的值,等等。由于時代、思維方式、編程任務(wù)以及個人喜好等因素的不同,出現(xiàn)了許許多多的描述方式,對這些不同的描述方式,我們就將它們區(qū)分開來,稱之為不同的語言。例如前面所說的,要向屏幕打印一個“A”字符,在BASIC語言中的對應(yīng)描述是:
PRINT “A”
而下面則是Pascal下的描述:
writeln(‘A’);
再給出C語言的:
printf(“A”);
而C++則更傾向于下面的表述:
cout << “A”;
下面是Java:
System.out.print("A ");
以上,僅從輸出“A”字符這樣一個最基本的實現(xiàn)就可以看出,不同的語言之間往往有相當明顯的差別。當然,剛才我們所“領(lǐng)略”到的只是形式上的區(qū)別,而其背后的思想差異才是最重要的。
此外,程序語言還有高、低級之分。噢,不要望文生義地認為所謂的“低級”語言實現(xiàn)的功能會比“高級”語言實現(xiàn)的要少——恰恰相反,最“低級”的語言可以實現(xiàn)所有的功能,而那些太過“高級”的語言反而可能會有這樣那樣的限制。原來,這里的高、低并不是指語言功能強大與否,而是指語言描述能力,或者說是語言與人類自然語言(思維方式)的接近程度。實際上,計算機唯一能“懂”的是最“低級”的機器語言,說白了就是像0101這樣的二進制指令代碼。但成天用0101來寫指令實在太累,也很容易出錯,所以就出現(xiàn)了相對“高級”一點的匯編語言,它和機器語言基本上可以做到一一對應(yīng),但它的寫法是充滿了類似于mov、jmp這樣的助記符,而不是令人頭大的0101們。所以實在是方便了不少。當匯編代碼寫好之后,再由一個可以自動轉(zhuǎn)換的代碼的程序來將它們轉(zhuǎn)換成為可執(zhí)行的二進制代碼。
雖然匯編語言相對于機器語言來說著實是親切不少,但由于它很大程度上畢竟是機器語言的簡單對應(yīng)式的替換,因此在編寫一些復雜的大型程序時尤其煩瑣;而由于其表達能力過于簡單,所以錯誤更是難以避免;此外,由于匯編語言所對應(yīng)的機器語言實際上可以看作是一系列對硬件與系統(tǒng)較底層的操作,所以一旦換用不同的系統(tǒng)平臺或者機器,幾乎必須要進行修改甚至重新編寫。即使是像前面輸出“A”這樣一個簡單的操作,在Windows和Unix下就要分別寫兩個不同的匯編版本。其實我們所要求的功能是一樣的,但匯編語言的抽象程度太低了,所以體現(xiàn)不出來。為此,人們又開發(fā)出各種高級程序語言,像Fortran、Ada、LISP、BASIC、Pascal、C/C++以及近年來出現(xiàn)的Java、C#等等。由于它們的抽象度比較高,源代碼無須與硬件、系統(tǒng)底層操作對應(yīng),所以移植性比匯編要好得多,理想的情況下甚至不必為不同的系統(tǒng)平臺或者機器改動源代碼。
自此,程序就分為了兩類,一類稱為“源程序”,就是程序員用各種相對高級一些的語言編寫的人們易于讀懂的的代碼,包括前面提及的匯編代碼,以及其它所有的高級程序語言編寫的代碼;另一類則稱為“可執(zhí)行程序”,就是由匯編代碼或者高級語言代碼經(jīng)過程序的轉(zhuǎn)換后最終得到的二進制程序,我們的電腦可以直接識別并執(zhí)行它,所以叫“可執(zhí)行”。與之相應(yīng)的概念,還有“源代碼”/“可執(zhí)行代碼”、“源文件”/“可執(zhí)行文件”等等。
你一定容易理解,“源代碼”就是指以匯編或者高級語言所編寫的代碼,這些代碼我們將它們以文件的形式保存起來,就成為源文件。大多數(shù)的源文件都是以最簡單的文本形式進行存儲的,和我們常見的.txt文件沒有區(qū)別,只不過為了表明它是源文件,所以通常會起不同的擴展名,像BASIC語言為.bas,C語言為.c等等。因此,你可以用記事本這樣的簡單的文本編輯器對它們進行創(chuàng)建或者編輯。
2.從源代碼到執(zhí)行
前面說過,計算機只認得二進制的可執(zhí)行代碼,而我們更樂意使用匯編語言和各種高級語言。那么,我們編寫的這些源程序最終是如何被執(zhí)行的呢?
對于匯編語言,前面已經(jīng)提到過一個類似于轉(zhuǎn)換器的程序,它可以把我們寫的匯編語言“翻譯”成機器語言,然后保存在一個它生成的程序文件中,就得到了我們所要的可執(zhí)行程序。
而高級語言家族則非常豐富,所以對這個問題的解決也是八仙過海,各顯神通。大體分來,也不外乎兩大類:編譯型和解釋型。
我們先看看編譯型,其實它和前面的匯編語言是一樣的:也是有一個負責翻譯的程序來對我們的源代碼進行轉(zhuǎn)換,生成相對應(yīng)的可執(zhí)行代碼。這個過程說得專業(yè)一點,就稱為編譯(Compile),而負責編譯的程序自然就稱為編譯器(Compiler)。如果我們寫的程序代碼都包含在一個源文件中,那么通常編譯之后就會直接生成一個可執(zhí)行文件,我們就可以直接運行了。但對于一個比較復雜的項目,為了方便管理,我們通常把代碼分散在各個源文件中,作為不同的模塊來組織。這時編譯各個文件時就會生成目標文件(Object file)而不是前面說的可執(zhí)行文件。一般一個源文件的編譯都會對應(yīng)一個目標文件。這些目標文件里的內(nèi)容基本上已經(jīng)是可執(zhí)行代碼了,但由于只是整個項目的一部分,所以我們還不能直接運行。待所有的源文件的編譯都大功告成,我們就可以最后把這些半成品的目標文件“打包”成一個可執(zhí)行文件了,這個工作由另一個程序負責完成,由于此過程好像是把包含可執(zhí)行代碼的目標文件連接裝配起來,所以又稱為鏈接(Link),而負責鏈接的程序就叫……就叫鏈接程序(Linker)。鏈接程序除了鏈接目標文件外,可能還有各種資源,像圖標文件啊、聲音文件啊什么的,還要負責去除目標文件之間的冗余重復代碼,等等,所以……也是挺累的。鏈接完成之后,一般就可以得到我們想要的可執(zhí)行文件了。
上面我們大概地介紹了編譯型語言的特點,現(xiàn)在再看看解釋型。噢,從字面上看,“編譯”和“解釋”的確都有“翻譯”的意思,它們的區(qū)別則在于翻譯的時機安排不大一樣。打個比方:假如你打算閱讀一本外文書,而你不知道這門外語,那么你可以找一名翻譯,給他足夠的時間讓他從頭到尾把整本書翻譯好,然后把書的母語版交給你閱讀;或者,你也立刻讓這名翻譯輔助你閱讀,讓他一句一句給你翻譯,如果你想往回看某個章節(jié),他也得重新給你翻譯。
兩種方式,前者就相當于我們剛才所說的編譯型:一次把所有的代碼轉(zhuǎn)換成機器語言,然后寫成可執(zhí)行文件;而后者就相當于我們要說的解釋型:在程序運行的前一刻,還只有源程序而沒有可執(zhí)行程序;而程序每執(zhí)行到源程序的某一條指令,則會有一個稱之為解釋程序的外殼程序?qū)⒃创a轉(zhuǎn)換成二進制代碼以供執(zhí)行,總言之,就是不斷地解釋、執(zhí)行、解釋、執(zhí)行……所以,解釋型程序是離不開解釋程序的。像早期的BASIC就是一門經(jīng)典的解釋型語言,要執(zhí)行BASIC程序,就得進入BASIC環(huán)境,然后才能加載程序源文件、運行。解釋型程序中,由于程序總是以源代碼的形式出現(xiàn),因此只要有相應(yīng)的解釋器,移植幾乎不成問題。編譯型程序雖然源代碼也可以移植,但前提是必須針對不同的系統(tǒng)分別進行編譯,對于復雜的工程來說,的確是一件不小的時間消耗,況且很可能一些細節(jié)的地方還是要修改源代碼。而且,解釋型程序省卻了編譯的步驟,修改調(diào)試也非常方便,編輯完畢之后即可立即運行,不必像編譯型程序一樣每次進行小小改動都要耐心等待漫長的Compiling…Linking…這樣的編譯鏈接過程。不過凡事有利有弊,由于解釋型程序是將編譯的過程放到執(zhí)行過程中,這就決定了解釋型程序注定要比編譯型慢上一大截,像幾百倍的速度差距也是不足為奇的。
編譯型與解釋型,兩者各有利弊。前者由于程序執(zhí)行速度快,同等條件下對系統(tǒng)要求較低,因此像開發(fā)操作系統(tǒng)、大型應(yīng)用程序、數(shù)據(jù)庫系統(tǒng)等時都采用它,像C/C++、Pascal/Object Pascal(Delphi)、VB等基本都可視為編譯語言,而一些網(wǎng)頁腳本、服務(wù)器腳本及輔助開發(fā)接口這樣的對速度要求不高、對不同系統(tǒng)平臺間的兼容性有一定要求的程序則通常使用解釋性語言,如Java、JavaScript、VBScript、Perl、Python等等。
但既然編譯型與解釋型各有優(yōu)缺點又相互對立,所以一批新興的語言都有把兩者折衷起來的趨勢,例如Java語言雖然比較接近解釋型語言的特征,但在執(zhí)行之前已經(jīng)預先進行一次預編譯,生成的代碼是介于機器碼和Java源代碼之間的中介代碼,運行的時候則由JVM(Java的虛擬機平臺,可視為解釋器)解釋執(zhí)行。它既保留了源代碼的高抽象、可移植的特點,又已經(jīng)完成了對源代碼的大部分預編譯工作,所以執(zhí)行起來比“純解釋型”程序要快許多。而像VB6(或者以前版本)、C#這樣的語言,雖然表面上看生成的是.exe可執(zhí)行程序文件,但VB6編譯之后實際生成的也是一種中介碼,只不過編譯器在前面安插了一段自動調(diào)用某個外部解釋器的代碼(該解釋程序獨立于用戶編寫的程序,存放于系統(tǒng)的某個DLL文件中,所有以VB6編譯生成的可執(zhí)行程序都要用到它),以解釋執(zhí)行實際的程序體。C#(以及其它.net的語言編譯器)則是生成.net目標代碼,實際執(zhí)行時則由.net解釋系統(tǒng)(就像JVM一樣,也是一個虛擬機平臺)進行執(zhí)行。當然.net目標代碼已經(jīng)相當“低級”,比較接近機器語言了,所以仍將其視為編譯語言,而且其可移植程度也沒有Java號稱的這么強大,Java號稱是“一次編譯,到處執(zhí)行”,而.net則是“一次編碼,到處編譯”。呵呵,當然這些都是題外話了。總之,隨著設(shè)計技術(shù)與硬件的不斷發(fā)展,編譯型與解釋型兩種方式的界限正在不斷變得模糊。
----------------------------------------------
沒有編程基礎(chǔ)的人我建議你去先搞點比較好的編程課程視頻來看,
這里有計算機各種視頻教程和大量資料!
http://www.javavc.com
值得推薦★★★★★
希望能為廣大的編程愛好者提供方便。