《C程序設(shè)計》課件第1章_第1頁
《C程序設(shè)計》課件第1章_第2頁
《C程序設(shè)計》課件第1章_第3頁
《C程序設(shè)計》課件第1章_第4頁
《C程序設(shè)計》課件第1章_第5頁
已閱讀5頁,還剩132頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第一章C語言基礎(chǔ)1.1計算機(jī)組成1.2數(shù)據(jù)表示和數(shù)制1.3算法1.4編程語言和編譯1.5C語言的發(fā)展簡史與優(yōu)點1.6C語言的定義1.7C語言的使用1.8C程序舉例習(xí)題1.1計算機(jī)組成如今計算機(jī)已經(jīng)滲透到生活的方方面面,可謂無孔不入、無所不在。作為生活在計算機(jī)時代的讀者,這種現(xiàn)代化的成長經(jīng)歷或許會讓你對計算機(jī)有一個感性的認(rèn)識。但是本書并不關(guān)心計算機(jī)本身,不過了解一些簡單的計算機(jī)知識將有助于你理解程序是怎樣在計算機(jī)中運行的。計算機(jī)是一種可以輸入、存儲、處理和輸出各種數(shù)據(jù)的機(jī)器。這些機(jī)器可以接收、存儲、處理和輸出信息,而且能夠處理各種各樣的數(shù)據(jù):數(shù)字、文本、圖像、圖形、聲音等等。構(gòu)成計算機(jī)系統(tǒng)的各種設(shè)備(如鍵盤、屏幕、鼠標(biāo)、磁盤、內(nèi)存、光盤和處理器)稱為硬件。它們是有形的,可觸摸得到的?,F(xiàn)代計算機(jī)是一種通用的機(jī)器,可以完成各種各樣的任務(wù)。為實現(xiàn)這些通用的功能,計算機(jī)必須是可編程的。也就是說需要給計算機(jī)提供一組指令來控制計算機(jī)解決特定問題所需要的各個具體步驟,這組指令稱為計算機(jī)程序或者軟。正是軟件和硬件的互相配合才使得完成各種計算成為可能。從小小的計算器到國家氣象局天氣預(yù)報的巨型計算機(jī),其基本組成都是相同的。圖1.1給出了現(xiàn)今計算機(jī)系統(tǒng)的基本組成部件:中央處理單元(CPU)、內(nèi)存、總線、輔助存儲設(shè)備(磁盤等)、輸入/輸出(I/O)設(shè)備(鼠標(biāo)、鍵盤等)。圖1.1計算機(jī)的基本組成

1.主存儲器每當(dāng)計算機(jī)執(zhí)行一個程序,計算機(jī)必須以某種方式存儲程序代碼本身和計算中所涉及的數(shù)據(jù)。通常計算機(jī)中可以存儲和獲取信息的硬件設(shè)備都被認(rèn)為是存儲設(shè)備。但是只有程序運行時所使用的存儲設(shè)備才稱得上是主存儲器,也就是我們通常所說的內(nèi)存。內(nèi)存是一些有序排列的存儲單元,這些存儲單元包含在由集成電路組成的硅芯片當(dāng)中,因此其工作效率非常高,使得CPU可以快速訪問其中的內(nèi)容。各個內(nèi)存存儲單元既可以保存數(shù)據(jù),也可以保存指令,如圖1.2所示。現(xiàn)代計算機(jī)內(nèi)存由一片特殊的集成電路芯片——RAM來實現(xiàn)。RAM代表隨機(jī)訪問存儲器,允許程序在任何時間訪問任何的內(nèi)存單元。RAM具有易失性,需要持續(xù)的電源以保存所存儲的數(shù)據(jù),因此,一旦斷電會導(dǎo)致所有已經(jīng)存儲的數(shù)據(jù)丟失。圖1.2內(nèi)存中的程序和數(shù)據(jù)

2.輔助存儲器除內(nèi)存外,計算機(jī)還需要其它存儲器。這主要是因為:第一,計算機(jī)需要永久地或者半永久地保存一些信息,以便在計算機(jī)掉電或關(guān)機(jī)后還能夠再使用這些信息;第二,通常計算機(jī)需要存儲遠(yuǎn)大于內(nèi)存容量的信息。圖1.3是一些經(jīng)常使用的輔助存儲設(shè)備和存儲介質(zhì)。由圖可知,訪問輔助存儲單元中的信息要比訪問主內(nèi)存中的信息慢得多,但輔助存儲單元的單位成本比主內(nèi)存的單位成本低得多。圖1.3不同存儲器關(guān)系圖

3.中央處理單元(CPU)中央處理單元(CentralProcessingUnit,CPU)是計算機(jī)的大腦,是硬件系統(tǒng)的核心。它執(zhí)行實際的計算并控制整個計算機(jī)的操作。現(xiàn)代計算機(jī)的CPU位于采用大規(guī)模集成電路工藝制成的芯片(又稱微處理器芯片)當(dāng)中,包括兩個主要部分:算術(shù)邏輯單元和控制單元。CPU當(dāng)前的指令和數(shù)據(jù)都臨時存儲在稱為寄存器的超高速存儲單元中。

CPU中的控制單元(ControlUnit,CU)負(fù)責(zé)從存儲器中取出指令,并對指令進(jìn)行譯碼;根據(jù)指令的要求,按時間的先后順序,負(fù)責(zé)向其它各部件發(fā)出控制信號,保證各部件協(xié)調(diào)一致地工作,一步一步地完成各種操作??刂茊卧?CU)主要由指令寄存器、譯碼器、程序計數(shù)器、操作控制器等組成。

CPU中的算術(shù)邏輯單元(ArithmeticLogicUnit,ALU)對計算機(jī)數(shù)據(jù)進(jìn)行加工處理,包括算術(shù)運算(加、減、乘、除等)和邏輯運算(與、或、非、異或、比較等)。

ALU使用寄存器來存取正在處理的數(shù)據(jù),使用稱為累加寄存器的專用寄存器臨時保存運算或比較的結(jié)果。圖1.4顯示了CPU如何處理將4和5相加的這條指令。首先,控制器將要處理的數(shù)據(jù)(本例中為4和5)從RAM送至ALU中的寄存器;接著控制單元給ALU發(fā)送一個信號,指示ALU把兩個數(shù)相加;然后ALU將結(jié)果(本例中為9)存儲到累加寄存器中;最后控制單元把累加寄存器中的數(shù)據(jù)發(fā)送到RAM,這樣數(shù)據(jù)就可以輸出、存盤或者進(jìn)行其它處理了。圖1.4CPU如何處理兩個數(shù)相加

4.總線總線(Bus)是一些貫穿整個計算機(jī)系統(tǒng)的電子管道,是計算機(jī)的神經(jīng)系統(tǒng),用于在CPU和計算機(jī)的其它設(shè)備之間傳輸信息。微型計算機(jī)硬件結(jié)構(gòu)最重要的特點是總線結(jié)構(gòu)。它將信號線分成三大類,并歸結(jié)為數(shù)據(jù)總線(DataBus)、地址總線(AddressBus)和控制總線(ControlBus)。這種結(jié)構(gòu)很適合計算機(jī)部件的模塊化生產(chǎn),促進(jìn)了微型計算機(jī)的普及。

5.輸入單元為了使用計算機(jī),我們必須通過某種方式把數(shù)據(jù)送入計算機(jī)或者從計算機(jī)中得到數(shù)據(jù)。所有的輸入/輸出設(shè)備都通過一個控制器或者適配器連接到I/O總線。控制器本身就是輸入/輸出設(shè)備或者系統(tǒng)主板上的芯片組,而適配器則是一種必須插到主板擴(kuò)展插槽上的接口卡。輸入單元是計算機(jī)的感知器,用于從輸入設(shè)備(鍵盤、鼠標(biāo))獲取信息。鍵盤(Keyboard)是最常見的輸入設(shè)備。標(biāo)準(zhǔn)鍵盤上的按鍵排列可以分為三個區(qū)域:字符鍵區(qū)、功能鍵區(qū)和數(shù)字鍵區(qū)(數(shù)字小鍵盤)。

6.輸出單元輸出單元是計算機(jī)的受動器,用于輸出信息到屏幕、打印機(jī)或者控制其它設(shè)備。顯示器(Display)是微型機(jī)不可缺少的輸出設(shè)備,用戶通過它可以很方便地查看送入計算機(jī)的程序、數(shù)據(jù)、圖形等信息及經(jīng)過計算機(jī)處理后的中間結(jié)果、最后結(jié)果。顯示器是人機(jī)對話的主要工具。1.2數(shù)據(jù)表示和數(shù)制1.2.1數(shù)據(jù)表示計算機(jī)只能識別“0”和“1”。那么,計算機(jī)如何在存儲器中用“0”和“1”來表示上面的這些數(shù)據(jù)呢?這就是本小節(jié)數(shù)據(jù)表示需要解決的問題。正如1.1節(jié)所討論的,計算機(jī)是處理數(shù)據(jù)的機(jī)器。由于數(shù)據(jù)有各種各樣的表示形式,例如,數(shù)、文字、圖像、音頻和視頻等,要為每種不同的數(shù)據(jù)使用不同的計算機(jī)來處理,顯然是不切實際的和不經(jīng)濟(jì)的。有效的解決辦法就是使用一種統(tǒng)一的數(shù)據(jù)表示方法。所有類型的數(shù)據(jù)輸入到計算機(jī)內(nèi)部以后都被轉(zhuǎn)換成一種統(tǒng)一的表示格式,這種統(tǒng)一的表示格式就是比特模式(BitPattern)。在討論比特模式之前,必須先定義什么是比特(bit)。一個比特(二進(jìn)制數(shù)字)是計算機(jī)存儲數(shù)據(jù)所使用的最小單元,它要么是0,要么是1。一個比特也表示了一臺設(shè)備只能取兩種狀態(tài)之一。例如,開關(guān)只能是開(On)或者關(guān)(Off)。因此,一個開關(guān)可以存儲一個比特?,F(xiàn)在,計算機(jī)使用大量的兩種狀態(tài)的設(shè)備來存儲數(shù)據(jù)。單個比特?zé)o法解決數(shù)據(jù)的表示問題。對于大數(shù)、文本、圖像等數(shù)據(jù),我們需要使用比特模式,或比特序列來存儲。圖1.5給出了由16個比特組成的比特模式。它是0和1的組合。這意味著需要16個電子開關(guān)來存儲這個比特模式。圖1.5比特模式具體到存儲器內(nèi)所保存的某個比特模式代表什么含義,則是程序的責(zé)任所在。例如,比特模式“01000001”我們既可以理解為大寫字母“A”,又可以理解為整數(shù)65。但不管怎樣,有了比特模式,我們就可以用它來表示各種不同的數(shù)據(jù)。例如,常見的英文字母符號就可以用不同的比特模式來表示。我們可以把字符串“BYTE”分別用四種不同的比特模式來表示,如圖1.6所示。圖1.6使用比特模式表示字母我們也可以使用比特模式來表示一張圖片上某個像素點的顏色,例如可以用三種比特模式來分別表示一個像素點的紅色(R)、綠色(G)和藍(lán)色(B)的強(qiáng)度,如圖1.7所示。圖1.7像素顏色的比特模式表示一般,長度為8的比特模式我們稱之為一個字節(jié)(Byte)。這8個比特總共有256(28)種不同的開-關(guān)條件組合,從全關(guān)00000000到全開11111111。例如,字母“A”的8比特表示為01000001,星號“*”的8比特表示為00101010。然而計算機(jī)怎么知道比特值01000001表示字母“A”呢?當(dāng)用戶敲擊鍵盤的“A”時,系統(tǒng)就會從這個特定的鍵發(fā)送一個信號到內(nèi)存里,并設(shè)置內(nèi)存中的一個字節(jié)的比特值為01000001。接下來用戶就可以任意地對這個字節(jié)進(jìn)行操作,甚至把字母“A”輸出到顯示器或者打印機(jī)上,如圖1.8所示。圖1.8字母“A”的輸出內(nèi)存中的每一個字節(jié)都有一個惟一的地址。由于計算機(jī)只能區(qū)分0和1比特,因此其工作模式屬于基2計數(shù)系統(tǒng),我們稱之為二進(jìn)制系統(tǒng)。事實上,詞“bit”來自于“BinarydigIT”的縮寫。一個字節(jié)當(dāng)中的比特可以按照從右往左的順序?qū)λM(jìn)行0到7的編號。圖1.9所示表示對字母“A”的8個比特進(jìn)行編號。最左邊的比特位我們稱之為最高有效位(MostSignificantBit,MSB),而最右邊的比特位稱為最低有效位(LeastSignificantBit,LSB)。圖1.9比特位的編號1.2.2數(shù)制數(shù)制是指用一組固定的數(shù)字和一套統(tǒng)一的規(guī)則來表示數(shù)目的方法。其中兩個最基本的概念是:

·基數(shù)(Radix):一個計數(shù)制所包含的數(shù)字符號的個數(shù)稱為該數(shù)制的基數(shù),通常用R表示,如二進(jìn)制的R為2。

·

位值(權(quán)):任何一個R進(jìn)制的數(shù)都是由一串?dāng)?shù)碼表示的,其中每一位數(shù)碼所表示的實際值大小,除數(shù)碼本身的數(shù)值外,還與它所處的位置有關(guān),由位置決定的值就叫位值(或稱權(quán),PositionalValue)。位值用基數(shù)R的i次冪(Ri)表示。日常生活采用的是十進(jìn)制數(shù)制,它由0、1、2、3、4、5、6、7、8、9共10個數(shù)字符號組成,數(shù)字符號在不同的數(shù)位上表示不同的數(shù)值,每個數(shù)位均逢十進(jìn)一。十進(jìn)制數(shù)的基數(shù)為10,位權(quán)為10的指數(shù)次冪。二進(jìn)制數(shù)使用“0”和“1”這兩個數(shù)字符號,遵循“逢二進(jìn)一”的原則。例如:0+0=0;1+0=0+1=1;1+1=10;+10=11;1+11=100。在計算機(jī)中,一個二進(jìn)制位又稱為一個比特(Bit),是表示數(shù)據(jù)的最小單位。二進(jìn)制數(shù)的基數(shù)為2,位權(quán)為2的指數(shù)次冪。八進(jìn)制數(shù)的示數(shù)符號有8個:0、1、2、3、4、5、6、7,“逢八進(jìn)一”,它的基數(shù)為8,位權(quán)為8的指數(shù)次冪。十六進(jìn)制數(shù)的示數(shù)符號有16個:0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F,“逢十六進(jìn)一”,它的基數(shù)為16,位權(quán)為16的指數(shù)次冪。八進(jìn)制數(shù)和十六進(jìn)制數(shù)均是為了方便書寫和閱讀時使用的,在計算機(jī)內(nèi)部實際上所有的數(shù)均是二進(jìn)制數(shù)。表1.1給出了十進(jìn)制數(shù)字0~15所對應(yīng)的二、八、十六進(jìn)制數(shù)。表1.1十進(jìn)制數(shù)與二、八、十六進(jìn)制數(shù)對照表1.2.3數(shù)制之間的轉(zhuǎn)換通常人們習(xí)慣在一個數(shù)的后面加上一個字母B、D、H、O來區(qū)分其前面表示的一個數(shù)用的是什么數(shù)制。例如:101.01B表示二進(jìn)制數(shù)101.01;A2BH表示十六進(jìn)制數(shù)A2B等。

1)非十進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)利用按權(quán)展開的方法,可以將任意數(shù)制的一個數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)。例如:將二進(jìn)制01000001轉(zhuǎn)換成十進(jìn)制數(shù)如下:其轉(zhuǎn)換結(jié)果是:01000001B=0×27+1×26+0×25+0×24+0×23+0×22+0×21+1×20=64+1=65D。假定要將125.7O轉(zhuǎn)換成十進(jìn)制數(shù),其轉(zhuǎn)換過程如下:其轉(zhuǎn)換結(jié)果是:125.7O=1×82+2×81+5×80+7×8-1=64+16+5+0.875=85.875D。在八進(jìn)制中,小數(shù)點左邊的那位的權(quán)是1(80),再左邊一位的權(quán)是8(81),依此類推。而小數(shù)點右邊那些位的權(quán),則是用基數(shù)(在此為8)去除,因此緊跟八進(jìn)制小數(shù)點右邊那位的權(quán)是1/8,即0.125,下一位是1/64,即0.015625。

2)十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)把十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)的方法是采用“除二取余”法。即把十進(jìn)制數(shù)除以2,所得余數(shù)作為二進(jìn)制數(shù)的最低位數(shù),然后再除以2,所得余數(shù)作為次低位數(shù),如此反復(fù),直到商為零為止。例如把十進(jìn)制數(shù)23轉(zhuǎn)換為二進(jìn)制數(shù)的過程如圖1.10所示,由此可得,23D=(10111)B。。圖1.10十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)

3)二進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制數(shù)將二進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制數(shù)的方法是:從個位數(shù)開始向左按每四位二進(jìn)制數(shù)一組劃分,不足四位的組前面以0補(bǔ)齊,然后將每組四位二進(jìn)制數(shù)代之以一位十六進(jìn)制數(shù)即可。例如,要將二進(jìn)制數(shù)1111101011011轉(zhuǎn)換成十六進(jìn)制數(shù),其轉(zhuǎn)換過程如下:最終轉(zhuǎn)換結(jié)果為:1111101011011B=1F5BH。

4)十六進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)將十六進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù),其過程與將二進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制數(shù)相反。即將每一位十六進(jìn)制數(shù)代之以與其等值的四位二進(jìn)制數(shù)即可。例如,要將十六進(jìn)制數(shù)26CE轉(zhuǎn)換成二進(jìn)制數(shù),其轉(zhuǎn)換過程如下:所以:26CEH=10011011001110B1.2.4數(shù)的補(bǔ)碼表示我們知道,一個數(shù),例如十進(jìn)制84,它的16位二進(jìn)制表示是0000000001010100。但是,當(dāng)同一個數(shù)84被看成是+84時,符號也必須作為二進(jìn)制表示的一部分進(jìn)行存儲。因此,對于有符號數(shù),最左邊的有效位通常用于存儲數(shù)的符號(Sign),而剩下的比特位表示數(shù)的量值(Magnitude)。這樣,+84的符號-量值表示為0000000001010100,同84的二進(jìn)制表示一樣。盡管這兩種表示方法一樣,但是最高有效位(MSB)——第15比特的含義完全不一樣。當(dāng)以二進(jìn)制存儲84時,MSB是量值的一部分;而存儲帶符號數(shù)+84時,MSB為0表示它是一個正數(shù),其量值由剩下的15個比特位決定。對于負(fù)整數(shù),同樣可以用符號-量值表示,如-47可表示為1000000000101111。但是這種符號-量值表示方法有很多不足。首先,注意到0的符號-量值表示有兩種形式:0000000000000000和1000000000000000。其次,對于計算機(jī)來說要同時提供整數(shù)的二進(jìn)制加法和減法運算并非易事。因此,在這一節(jié),我們將尋求計算機(jī)整數(shù)的其它存儲方法:1的補(bǔ)碼表示法和2的補(bǔ)碼表示法。

1.

1的補(bǔ)碼表示法對于正整數(shù),其1的補(bǔ)碼表示就是該整數(shù)的符號-量值表示。如+84的1的補(bǔ)碼表示就是0000000001010100。對于負(fù)整數(shù),1的補(bǔ)碼表示按下列規(guī)則計算:(2n-1)減去該數(shù)的量值,n為二進(jìn)制比特數(shù),在此等于16。如-36的1的補(bǔ)碼表示為:步驟一:把整數(shù)的量值轉(zhuǎn)換為二進(jìn)制:

+36D=0000000000100100B步驟二:因為n=16,所以

216-1=65535D=1111111111111111B上述求1的補(bǔ)碼表示方法看起來非常繁瑣。我們注意到:+36的1的補(bǔ)碼表示為:0000000000100100-36的1的補(bǔ)碼表示為:1111111111011011我們對+36和-36的1的補(bǔ)碼表示進(jìn)行逐位比特比較會發(fā)現(xiàn):它們的對應(yīng)比特位是互反的。因此,更簡潔的求1的補(bǔ)碼表示方法是對相應(yīng)的正整數(shù)逐位求反。

2.2的補(bǔ)碼表示法對于正整數(shù),其2的補(bǔ)碼表示、1的補(bǔ)碼表示和符號-量值表示一樣。對于負(fù)整數(shù),2的補(bǔ)碼表示按下列規(guī)則計算:(2n)減去該數(shù)的量值,n為二進(jìn)制比特數(shù),在此等于16。顯然,2的補(bǔ)碼表示可以通過1的補(bǔ)碼表示加1來實現(xiàn)。如,-36的2的補(bǔ)碼表示為有了2的補(bǔ)碼表示,我們可以驗證:

36-36=36+(-36)=0,即

(36)(-36)(0)因此,2的補(bǔ)碼表示可以把整數(shù)的加法和減法運算統(tǒng)一起來,而且±0的2的補(bǔ)碼表示也是一樣的,都是0000000000000000。所以,大部分計算機(jī)表示有符號數(shù)時都使用2的二進(jìn)制補(bǔ)碼表示法。1.2.5字符編碼字符編碼(CharacterCode)就是規(guī)定用怎樣的二進(jìn)制碼來表示字母、數(shù)字以及一些專用符號。由于這是一個涉及世界范圍內(nèi)有關(guān)信息表示、交換、處理、存儲的基本問題,因此字符的編碼都是以國家標(biāo)準(zhǔn)或者國際標(biāo)準(zhǔn)的形式頒布實施的。

1.ASCII

ASCII是由美國國家標(biāo)準(zhǔn)委員會制定的一種包括數(shù)字、字母、通用符號、控制符號在內(nèi)的字符編碼集,全稱為美國國家信息交換標(biāo)準(zhǔn)碼(AmericanStandardCodeforInformationInterchange),被國際標(biāo)準(zhǔn)化組織(ISO)指定為國際標(biāo)準(zhǔn)。ASCII碼是一種7位二進(jìn)制編碼,能表示27=128種國際上最通用的西文字符。ASCII碼是單字節(jié)碼,在計算機(jī)內(nèi)部,將最高位設(shè)為0。它常用于輸入/輸出設(shè)備,如鍵盤輸入、顯示器輸出等。

2.漢字編碼漢字也是字符,要進(jìn)行編碼后才能被計算機(jī)接受。漢字編碼目前有漢字信息交換碼、漢字輸入碼、漢字內(nèi)碼等。

1)漢字信息交換碼(國標(biāo)碼)漢字信息交換碼是用于漢字信息處理系統(tǒng)之間或者與通信系統(tǒng)之間進(jìn)行信息交換的漢字代碼,簡稱交換碼。它是為使系統(tǒng)、設(shè)備之間信息交換時采用統(tǒng)一的形式而制定的。

1981年頒布了《信息交換用漢字編碼字符集基本集》,代號“GB2312-80”,簡稱國標(biāo)碼。它是為使系統(tǒng)、設(shè)備之間信息交換時采用統(tǒng)一的形式而制定的。兩個字節(jié)存儲一個國標(biāo)碼。

2)漢字輸入碼為將漢字輸入計算機(jī)而編寫的代碼稱為漢字輸入碼,也叫外碼。如區(qū)位碼、拼音碼、智能ABC碼等。

3)漢字內(nèi)碼漢字內(nèi)碼是在計算機(jī)內(nèi)對漢字進(jìn)行存儲、處理的漢字代碼,它應(yīng)能滿足存儲、處理和傳輸?shù)囊蟆.?dāng)一個漢字輸入計算機(jī)后,就轉(zhuǎn)換為內(nèi)碼,然后才能在計算機(jī)中流動和處理。漢字內(nèi)碼多種多樣。目前,對應(yīng)于國標(biāo)碼一個漢字的內(nèi)碼常用2個字節(jié)存儲,并把每個字節(jié)的最高位置“1”作為漢字內(nèi)碼的標(biāo)識,以免與單字節(jié)的ASCII碼產(chǎn)生歧義性。漢字的機(jī)內(nèi)碼=漢字的國標(biāo)碼+8080H1.3算法計算機(jī)科學(xué)是借助計算機(jī)解決問題的學(xué)科。在此我們必須理解一個對于計算機(jī)科學(xué)和問題解決來說都很基礎(chǔ)的概念——算法(Algorithm)。我們可以簡單地認(rèn)為算法是一種解決問題的策略。但是,嚴(yán)格地說,要使某種解決問題的技術(shù)能被定義為是一種算法,必須滿足三個基本要求,即

·有窮性:一個算法應(yīng)包含有限的操作步驟而不能是無限的。

·確定性:算法中每一個步驟都應(yīng)當(dāng)是確定的,而不應(yīng)當(dāng)是含糊的、模棱兩可的、有歧義的。

·有效性:算法中每一個步驟應(yīng)當(dāng)能有效地執(zhí)行,并得到確定的結(jié)果。對于程序設(shè)計人員,必須會設(shè)計算法,并把算法用某種編程語言來實現(xiàn)。從這個角度來說,編程就是把所選用的算法翻譯成計算機(jī)能夠使用的語言。算法:解決問題的步驟和策略。算法的表示方法很多,在此我們主要討論自然語言表示法、偽代碼表示法和流程圖表示法。

1.自然語言表示法自然語言可以是中文、英文、數(shù)學(xué)表達(dá)式等等。用自然語言表示通俗易懂,缺點是可能文字冗長,不太嚴(yán)格,表達(dá)分支和循環(huán)的結(jié)構(gòu)不很方便。除了很簡單的問題,一般不用自然語言表示法。

2.偽代碼表示法偽代碼(Pseudocode)是用得最為普遍的定義算法的工具,它使用介于自然語言和計算機(jī)語言之間的文字和符號來描述算法。它通常包含類英語描述部分和結(jié)構(gòu)化代碼部分。類英語描述部分提供通俗易懂的、不太嚴(yán)格的語法表示;結(jié)構(gòu)化代碼部分提供各種擴(kuò)展的算法結(jié)構(gòu),如順序、選擇、循環(huán)、遞歸等。用偽代碼編寫的算法通常以算法名字作為開頭(例如找多個數(shù)的最小數(shù)),后面緊跟著該算法的目的(找最小的數(shù))、前提條件(提供數(shù)的列表)、需要的后處理(是否打印該最小數(shù))以及返回的結(jié)果(最小數(shù)),如圖1.11所示。圖1.11一個偽代碼例子我們認(rèn)為任何一個算法都應(yīng)該有返回值,即使沒有,也應(yīng)當(dāng)返回一個空值(NULL)。算法中的所有指令語句都應(yīng)當(dāng)進(jìn)行編號,且不跟任何符號結(jié)尾。在偽代碼中,通常用連續(xù)的數(shù)字或字母來表示同一級模塊中的連續(xù)語句。符號△后的內(nèi)容表示注釋。在偽代碼中,變量名和保留字不區(qū)分大小寫,變量不需聲明。賦值語句用符號←表示,x←exp表示將exp的值賦給x,其中x是一個變量,exp是一個與x同類型的變量或表達(dá)式(該表達(dá)式的結(jié)果與x同類型);多重賦值i←j←e是將表達(dá)式e的值賦給變量i和j,這種表示與j←e和i←e等價。例如:x←y

x←20*(y+1)

x←y←30

3.流程圖表示法流程圖表示算法,直觀形象,易于理解。流程圖是符號的組合,是圖形化表示。這些符號可以增加流程圖的可讀性和功能,但它們并不直接用于表示指令或者命令。常見的符號及其含義見表1.2。表1.2常見的符號及其含義求和是計算機(jī)科學(xué)中常用的一種算法。圖1.12所示的流程圖是通過循環(huán)結(jié)構(gòu)把多個數(shù)相加來計算其和的。這個求和算法包含三個邏輯部分:

(1)算法一開始對保存和的變量初始化。

(2)循環(huán)部分:每次取一個數(shù)同前面已經(jīng)計算得到的和相加。

(3)返回求和結(jié)果,退出循環(huán)。圖1.12求和算法流程圖表示1.4編程語言和編譯1.4.1什么是程序程序(Program)是指令的集合,它們告訴計算機(jī)如何對數(shù)據(jù)進(jìn)行處理以獲得編程者需要的信息,也是計算機(jī)在完成某項任務(wù)時必須嚴(yán)格遵循的。而指令則是由編程語言,如BASIC、C、Java的語句構(gòu)成的。程序和軟件(Software)這兩個詞可以互換使用。軟件主要有兩大類:系統(tǒng)軟件和應(yīng)用軟件。

1.系統(tǒng)軟件系統(tǒng)軟件是指管理、監(jiān)控和維護(hù)計算機(jī)資源以及開發(fā)其它軟件的計算機(jī)程序,包括操作系統(tǒng)、程序設(shè)計語言處理程序、支持軟件等。其中最重要的是操作系統(tǒng),它是控制和管理計算機(jī)的核心,用來對計算機(jī)系統(tǒng)中的各種軟、硬件資源進(jìn)行統(tǒng)一的管理和調(diào)度。它也是人和計算機(jī)的操作界面,我們使用計算機(jī)就是和操作系統(tǒng)打交道,我們學(xué)習(xí)使用計算機(jī)就是學(xué)習(xí)操作系統(tǒng)的使用。常用的操作系統(tǒng)有DOS、Windows、UNIX等。操作系統(tǒng)的部分程序永久存儲在只讀存儲器(ROM)芯片中,以便計算機(jī)開機(jī)后即可使用。計算機(jī)可以讀出ROM當(dāng)中的內(nèi)容,但不能向ROM中寫入數(shù)據(jù)。操作系統(tǒng)保存在ROM中的這部分程序,包括將操作系統(tǒng)其余代碼加載到內(nèi)存所必需的指令,這些代碼一般存儲在磁盤上。加載操作系統(tǒng)的這一過程稱之為引導(dǎo)計算機(jī)。

2.應(yīng)用軟件應(yīng)用軟件是指為解決各種實際問題而編制的計算機(jī)程序,如字處理應(yīng)用軟件、學(xué)籍管理系統(tǒng)等。應(yīng)用軟件可以由用戶自己編制,也可以由軟件公司編制。如MicrosoftOffice就是微軟(Microsoft)公司開發(fā)的辦公自動化軟件包,包括字處理軟件Word、表格處理軟件Excel、演示軟件Powerpoint等。1.4.2什么是編程編程,也稱為軟件開發(fā),就是為了產(chǎn)生這些指令的集合。這個過程通常包含以下6個步驟:

(1)程序說明書,也稱為程序定義或者程序分析。它需要編程人員詳細(xì)說明以下5項內(nèi)容:①程序的目標(biāo);②程序所需的輸入;③所期望的輸出;④處理要求;⑤文檔要求。這些內(nèi)容要求程序員對問題有一個清晰的概念,能夠不含糊的對問題進(jìn)行陳述,從而對解決問題的要求有一個準(zhǔn)確的理解。

(2)程序設(shè)計。在此階段,要求逐步寫出算法的一系列步驟來解決問題并驗證算法能否達(dá)到預(yù)定目的。這需要借助編程技術(shù)(例如結(jié)構(gòu)化編程技術(shù))來得到解決問題的步驟。結(jié)構(gòu)化編程技術(shù)包括自頂而下程序設(shè)計、偽代碼、流程圖和邏輯結(jié)構(gòu)。所謂自頂而下程序設(shè)計就是要列出程序的主要處理步驟或者要解決的各個子問題,然后通過解決每個子問題來解決最終的問題。這些子問題也被稱為程序模塊(ProgramModules)。所以這種方法就是把復(fù)雜的大的任務(wù)分解成為簡單的小的任務(wù),然后各個擊破、分而治之。理論上任何程序模塊可以用以下三種邏輯結(jié)構(gòu)來實現(xiàn):順序、分支和循環(huán)。使用這三種結(jié)構(gòu)可以編寫出所謂的結(jié)構(gòu)化程序。

(3)程序編碼。編碼是使用某種編程語言來實際編寫程序。程序員必須將算法中的每個步驟轉(zhuǎn)化為程序設(shè)計語言的一條或者多條語句。

(4)程序測試。它就是要檢驗寫好的程序是否能夠像預(yù)想的一樣工作。編程人員通常也稱測試為調(diào)試(Debug),就是要消除程序的語法和邏輯錯誤,找出程序中的“蟲子(Bug)”。語法錯誤是指違反編程語言規(guī)則的錯誤。例如,在C語言中所有的語句都必須以分號(Semicolon)結(jié)束,如果某條語句省略了分號,程序?qū)⒁驗檫@個錯誤而無法正常運行,如圖1.13所示。常見的錯誤測試方法包括:

·臺面測試(DeskChecking):是常常被忽略的重要測試部分。程序員必須像計算機(jī)那樣對程序代碼的每一行進(jìn)行仔細(xì)檢查以尋找其中的語法和邏輯錯誤,并檢驗程序執(zhí)行是否如期望所想。

·帶有樣本數(shù)據(jù)的手工測試(ManualTestingwithSampleData):利用正確和錯誤的數(shù)據(jù)手工地對程序的執(zhí)行過程進(jìn)行檢查。

·編譯測試(AttemptatTranslation):程序要在計算機(jī)上執(zhí)行,必須依靠編譯器進(jìn)行翻譯。編譯器試圖把程序員所編寫的編程語言代碼(如C代碼)翻譯成機(jī)器語言。在此過程中,程序必須是沒有語法錯誤的才能被正確地翻譯成機(jī)器語言。這類錯誤往往可以通過編譯器來識別,如圖1.13所示。圖1.13編譯器進(jìn)行語法檢查

·帶有樣本數(shù)據(jù)的計算機(jī)測試(TestingSampleDataonTheComputer):糾正完所有的語法錯誤后,就要使用各種樣本數(shù)據(jù)測試程序的邏輯錯誤。

·潛在用戶測試(TestingbyaSelectGroupofPotentialUsers):有時也稱為BetaTesting。這通常是程序測試的最后一個步驟,由潛在的用戶對程序進(jìn)行測試,并反饋回測試意見。

(5)程序文檔。建檔(Documenting)就是對程序的目的和處理過程進(jìn)行記錄。程序文檔包含了程序功能的描述、程序的處理流程和使用手冊。建檔貫穿整個軟件生命周期,只不過到此步驟為止,所有以往的文檔必須進(jìn)行重新檢查和完善,以得到最終的程序文檔。程序文檔對于所有潛在的同程序有關(guān)的用戶來說都是非常重要的。例如:對于程序的使用者,必須明確告訴他如何使用你的軟件,有些公司甚至還為此專門進(jìn)行用戶使用的培訓(xùn);對于編程人員,隨著時間的流逝,自己都有可能忘記當(dāng)初此程序是如何編寫的,更不用說后續(xù)參與到軟件開發(fā)的人員。因此,為了易于程序的后期更新和維護(hù),程序文檔應(yīng)當(dāng)足夠詳細(xì),盡量提供各種文字信息、程序的執(zhí)行流圖、程序列表、樣本輸出結(jié)果以及程序與系統(tǒng)的依賴關(guān)系等。

(6)程序維護(hù)。程序維護(hù)的目的是確保當(dāng)前程序能正確無誤地、高效地、穩(wěn)定地運行。隨著軟件的復(fù)雜程度日益增加,不可避免地存在各種各樣的軟件缺陷。通過程序維護(hù)可以改正先前沒有被發(fā)現(xiàn)的錯誤并從而保持軟件最新。很多軟件公司對程序要維護(hù)五年甚至更長時間,因此其費用往往很高,占應(yīng)用程序整個壽命開支的75%左右。1.4.3編程語言的分類計算機(jī)語言(ComputerLanguage)指用于人與計算機(jī)之間通信的語言。語言分為自然語言與人工語言兩大類。自然語言是人類在自身發(fā)展的過程中形成的語言,是人與人之間傳遞信息的媒介。人工語言指的是人們?yōu)榱四撤N目的而自行設(shè)計的語言。計算機(jī)語言就是人工語言的一種,它是人與計算機(jī)之間傳遞信息的媒介。計算機(jī)語言通常是一個能完整、準(zhǔn)確和規(guī)則地表達(dá)人們的意圖,并用以指揮或控制計算機(jī)工作的“符號系統(tǒng)”。計算機(jī)語言通常分為三類,即機(jī)器語言、匯編語言和高級語言。

圖1.14給出了C語言指令a=a+1;所對應(yīng)的匯編語言代碼和機(jī)器語言代碼。圖1-14C語言、匯編語言和機(jī)器語言代碼

1.機(jī)器語言機(jī)器語言是用二進(jìn)制代碼表示的計算機(jī)能直接識別和執(zhí)行的一種機(jī)器指令的集合。它是計算機(jī)的設(shè)計者通過計算機(jī)的硬件結(jié)構(gòu)賦予計算機(jī)的操作功能。機(jī)器語言具有靈活、直接執(zhí)行和速度快等特點。不過,編程人員很少用計算機(jī)能夠直接理解的語言編程,因為這種機(jī)器語言是一串串二進(jìn)制數(shù)的集合。編程人員要首先熟記所用計算機(jī)的全部指令代碼和代碼的涵義。例如,1000001111000000表示加法指令,用1000001111101000作為減法指令,使計算機(jī)執(zhí)行一次減法。編程序時,程序員得自己處理每條指令和每一數(shù)據(jù)的存儲分配及輸入/輸出,還得記住編程過程中每步所使用的工作單元處在何種狀態(tài)。這是一件十分繁瑣的工作,編寫程序花費的時間往往是實際運行時間的幾十倍或幾百倍。而且,編出的程序全是些0和1的指令代碼,直觀性差,還容易出錯。機(jī)器語言通常沒有統(tǒng)一的標(biāo)準(zhǔn),不同型號的CPU都有各自的機(jī)器語言。

2.匯編語言為了克服機(jī)器語言難讀、難編、難記和易出錯的缺點,人們就用與代碼指令實際含義相近的英文縮寫詞、字母和數(shù)字等符號來取代指令代碼(如用“addeax,1”代表一次加法,用“subeax,1”代表一次減法),于是就產(chǎn)生了匯編語言。所以說,匯編語言是一種用助記符表示的仍然面向機(jī)器的計算機(jī)語言。匯編語言亦稱符號語言。匯編語言是采用助記符號來編寫程序的,比用機(jī)器語言的二進(jìn)制代碼編程要方便些,這在一定程度上簡化了編程過程。匯編語言的特點是用符號代替了機(jī)器指令代碼,而且助記符與指令代碼一一對應(yīng),基本保留了機(jī)器語言的靈活性。使用匯編語言能面向機(jī)器并較好地發(fā)揮機(jī)器的特性,得到質(zhì)量較高的程序。匯編語言中由于使用了助記符號,用匯編語言編制的程序送入計算機(jī),計算機(jī)不能像用機(jī)器語言編寫的程序一樣直接識別和執(zhí)行,必須通過預(yù)先放入計算機(jī)的“匯編程序”的加工和翻譯,才能變成被計算機(jī)識別和處理的二進(jìn)制代碼程序。用匯編語言等非機(jī)器語言書寫好的符號程序稱為源程序,運行時匯編程序要將源程序翻譯成目標(biāo)程序。目標(biāo)程序是機(jī)器語言程序,它一經(jīng)被安置在內(nèi)存的預(yù)定位置上,就能被計算機(jī)的CPU處理和執(zhí)行。匯編語言的實質(zhì)和機(jī)器語言是相同的,都是直接對硬件操作,只不過指令采用了英文縮寫的標(biāo)識符,更容易識別和記憶,因而仍然是面向機(jī)器的語言,使用起來還是比較繁瑣,通用性也差。匯編語言是低級語言。但是,匯編語言用來編制系統(tǒng)軟件和過程控制軟件,其目標(biāo)程序占用內(nèi)存空間少,運行速度快,有著高級語言不可替代的用途。

3.高級語言不論是機(jī)器語言還是匯編語言都是面向硬件具體操作的,語言對機(jī)器的過分依賴,要求編程人員必須對硬件結(jié)構(gòu)及其工作原理都十分熟悉,這對非計算機(jī)專業(yè)人員是難以做到的,對于計算機(jī)的推廣應(yīng)用也是不利的。計算機(jī)事業(yè)的發(fā)展,促使人們?nèi)で笠恍┡c人類自然語言相接近且能為計算機(jī)所接受的語意確定、規(guī)則明確、自然直觀和通用易學(xué)的計算機(jī)語言。這種與自然語言相近并為計算機(jī)所接受和執(zhí)行的計算機(jī)語言稱為高級語言。高級語言是目前絕大多數(shù)編程者的選擇。和匯編語言相比,它不但將許多相關(guān)的機(jī)器指令合成為單條指令,并且去掉了與具體操作有關(guān)但與完成工作無關(guān)的細(xì)節(jié),例如使用堆棧、寄存器等,這就大大簡化了程序中的指令。同時,由于省略了很多細(xì)節(jié),編程人員也就不需要有太多的專業(yè)知識。高級語言接近人們習(xí)慣使用的自然語言和數(shù)學(xué)語言,使人們易于學(xué)習(xí)和使用。人們認(rèn)為,高級語言的出現(xiàn)是計算機(jī)發(fā)展史上一次驚人的成就,使千萬非專業(yè)人員能方便地編寫程序,按人們的指令操縱和使用計算機(jī)。語言進(jìn)化和抽象過程如圖1.15所示。圖1.15語言進(jìn)化和抽象過程例如要完成兩個數(shù)的相加,可以用以下語句來實現(xiàn):

a=a+1;這條語句表示“將變量a與1的值相加并把結(jié)果存入變量a(替換a原來的值)”。高級語言主要是相對于匯編語言而言的,它并不是特指某一種具體的語言,而是包括了很多編程語言,常用的高級語言有:BASIC(適合初學(xué)者應(yīng)用)、FORTRAN(用于數(shù)據(jù)計算)、COBOL(用于商業(yè)管理)、Pascal(用于教學(xué))、C(用于編寫系統(tǒng)軟件)、Ada(用于編寫大型軟件)、LISP(用于人工智能)等。不同的語言有其不同的功能,人們可根據(jù)不同領(lǐng)域的需要選用不同的語言。高級語言是面向用戶的語言。無論何種機(jī)型的計算機(jī),只要配備上相應(yīng)的高級語言的編譯或解釋程序,則用該高級語言編寫的程序就可以通用。計算機(jī)并不能直接地接受和執(zhí)行用高級語言編寫的源程序,源程序在輸入計算機(jī)時,通過“翻譯程序”翻譯成機(jī)器語言形式的目標(biāo)程序,計算機(jī)才能識別和執(zhí)行。但是計算機(jī)高級語言只定義了程序的屬性而不是程序的執(zhí)行方式,理解這一點很重要。程序執(zhí)行一般有兩種方式,即編譯方式和解釋方式。

·解釋方式:執(zhí)行方式類似于我們?nèi)粘I钪械摹巴暦g”,每當(dāng)源程序進(jìn)入計算機(jī)時,解釋程序邊掃描邊解釋,對逐句輸入進(jìn)行翻譯,而計算機(jī)則一句句執(zhí)行,并不生成可獨立執(zhí)行的可執(zhí)行目標(biāo)程序。因此應(yīng)用程序無法脫離其解釋器獨立運行,但這種方式比較靈活,可以動態(tài)地調(diào)整、修改應(yīng)用程序。

·編譯方式:編譯是指在應(yīng)用源程序執(zhí)行之前,就將程序源代碼“翻譯”成目標(biāo)代碼(機(jī)器語言),因此其目標(biāo)程序可以脫離其語言環(huán)境獨立執(zhí)行,使用比較方便、效率較高。但應(yīng)用程序一旦需要修改,必須先修改源代碼,再重新編譯生成新的目標(biāo)文件(*.OBJ)才能執(zhí)行。如果只有目標(biāo)文件而沒有源代碼,修改起來很不方便?,F(xiàn)在大多數(shù)的編程語言都是編譯型的,例如VisualC++、VisualFoxpro、Delphi等。程序被編譯之后,源代碼行對程序的執(zhí)行就毫無意義了。1.5

C語言的發(fā)展簡史與優(yōu)點

1.C語言的發(fā)展簡史

C語言是國際上廣泛流行的、很有發(fā)展前途的計算機(jī)高級語言。它適合于作為系統(tǒng)描述語言,既可用來寫系統(tǒng)軟件,也可用來寫應(yīng)用軟件。

C語言是第三代語言(面向過程的高級語言,第一代:機(jī)器語言;第二代:匯編語言)。以前的操作系統(tǒng)等系統(tǒng)軟件主要是由匯編語言編寫的(包括UNIX操作系統(tǒng)在內(nèi))。由于匯編語言依賴于計算機(jī)硬件,程序的可讀性和可移植性都比較差。為了提高可讀性和可移植性,最好改用高級語言,但一般高級語言難以實現(xiàn)匯編語言的某些功能(匯編語言可以直接對硬件進(jìn)行操作,例如,對內(nèi)存地址的操作、位操作等)。人們設(shè)想能否找到一種既具有一般高級語言特性,又具有低級語言特性的語言,集它們的優(yōu)點于一身。于是,C語言就在這種情況下應(yīng)運而生了。

C語言是在B語言的基礎(chǔ)上發(fā)展起來的,它的根源可以追溯到ALGOL60。1960年出現(xiàn)的ALGOL

60是一種面向問題的高級語言,它離硬件比較遠(yuǎn),不宜用來編寫系統(tǒng)程序。1963年英國的劍橋大學(xué)推出了CPL(CombinedProgrammingLanguage)語言,CPL語言在ALGOL60的基礎(chǔ)上接近硬件一些,但規(guī)模比較大,難以實現(xiàn)。1967年英國劍橋大學(xué)的MartinRichards對CPL語言作了簡化,推出了BCPL(BasicCombinedProgrammingLanguage)語言。

1970年美國貝爾實驗室的KenThompson以BCPL語言為基礎(chǔ),又作了進(jìn)一步簡化,設(shè)計出了很簡單的而且很接近硬件的B語言(取BCPL的第一個字母),并用B語言寫了第一個UNIX操作系統(tǒng),在PDP-7計算機(jī)上實現(xiàn)。但B語言過于簡單,功能有限。1972年至1973年間,貝爾實驗室的D.M.Ritchie在B語言的基礎(chǔ)上設(shè)計出了C語言(取BCPL的第二個字母)。C語言既保持了BCPL和B語言的優(yōu)點(精練、接近硬件),又克服了它們的缺點(過于簡單、數(shù)據(jù)無類型等)。最初的C語言只是為描述和實現(xiàn)UNIX操作系統(tǒng)提供一種工作語言而設(shè)計的,1973年,K.Thompson和D.M.Ritchie兩人合作把UNIX的90%以上代碼用C改寫(即UNIX第5版,原來的UNIX操作系統(tǒng)是1969年由美國的貝爾實驗室的K.Thompson和D.M.Ritchie開發(fā)成功的,是用匯編語言寫的)。后來,C語言被多次作了改進(jìn),但主要還是在貝爾實驗室內(nèi)部使用。直到1975年UNIX第6版公布后,C語言的突出優(yōu)點才引起人們的普遍注意。隨著UNIX的日益廣泛使用,C語言也迅速得到推廣,C語言和UNIX可以說是一對孿生兄弟,在發(fā)展過程中相輔相成。1978年以后,C語言已先后移植到大、中、小、微型機(jī)上,已獨立于UNIX和PDP了。現(xiàn)在C語言已風(fēng)靡全世界,成為世界上應(yīng)用最廣泛的幾種計算機(jī)語言之一。以1978年發(fā)表的UNIX第7版中的C編譯程序為基礎(chǔ),BrianW.Kernighan和DennisM.Ritchie(合稱K&R)合著了影響深遠(yuǎn)的名著《TheCProgrammingLanguage》,這本書中介紹的C語言成為后來廣泛使用的C語言版本的基礎(chǔ),它被稱為標(biāo)準(zhǔn)C。1983年,美國國家標(biāo)準(zhǔn)化協(xié)會(ANSI)根據(jù)C語言問世以來各種版本對C的發(fā)展和擴(kuò)充,經(jīng)過6年時間的修訂,于1989年發(fā)布了新的標(biāo)準(zhǔn),稱為ANSIC或者C89。

ANSIC比原來的標(biāo)準(zhǔn)C有了很大的發(fā)展。目前流行的C編譯系統(tǒng)都是以它為基礎(chǔ)的。本書的敘述基本上以ANSIC為基礎(chǔ)。目前廣泛流行的各種版本C語言編譯系統(tǒng)雖然基本部分是相同的,但也有一些不同。讀者可以參閱相關(guān)計算機(jī)系統(tǒng)的C語法手冊。

1999年又開發(fā)了新的C語言標(biāo)準(zhǔn),通常稱為C99。C99基本保留了C89的全部特性。新標(biāo)準(zhǔn)的主要改進(jìn)包括以下兩個方面:增加了數(shù)據(jù)庫函數(shù)和開發(fā)了一些專門的新特性,例如可變長度數(shù)組和restrict指針修飾符。

2.C語言的優(yōu)點在最近20年里,C已經(jīng)成為一種最重要的、最流行的程序設(shè)計語言。它是在人們的嘗試與喜愛之中成長起來的。當(dāng)用戶學(xué)習(xí)C語言的時候,將體驗到它的很多優(yōu)點。

C語言的優(yōu)點如下:

(1)設(shè)計時的考慮。C是一種融入強(qiáng)大控制功能的新式語言。計算機(jī)科學(xué)的理論和實踐認(rèn)為,這些控制功能都是需要的。C的設(shè)計使得用戶自然而然地去采用自頂向下的、結(jié)構(gòu)化的程序設(shè)計原則,以及模塊化的設(shè)計方法,從而獲得更加可靠、更加易于理解的程序。

(2)效率。C的效率非常高,它的設(shè)計充分發(fā)揮了當(dāng)代計算機(jī)各方面的效能。事實上,C提供了通常僅與匯編語言相聯(lián)系的某些精細(xì)的控制。只要用戶愿意,盡可能地微調(diào)自己的程序,以達(dá)到最快的速度,或者最有效地利用內(nèi)存。

(3)可移植性。C是一種可移植的語言。這意味著在一個系統(tǒng)上編制的C程序,只需很少的修改,甚至無需修改,即可在別的系統(tǒng)上運行。如果修改是必要的,那么,這些修改僅僅是在伴隨主程序的頭(Header)文件里變動幾個項目。就可移植性而言,C是領(lǐng)先者,C編譯器可供大約40個系統(tǒng)使用,它們運行在從八位的微處理器直至Cray超級巨型機(jī)上。

(4)高效而靈活。C高效而靈活(計算機(jī)文字中的兩大褒義詞),例如,高效、靈活的UNIX操作系統(tǒng)大部分是用C編寫的,其它的語言——諸如FORTRAN,Pascal、LISP、BASIC等的編譯器和解釋程序均以C來編制。因此,當(dāng)用戶在一臺UNIX機(jī)器上使用FORTRAN的時候,歸根結(jié)底,是一個C程序為用戶生成了最終的可執(zhí)行代碼。C程序已被用來求解各種物理和工程等問題,甚至為電影產(chǎn)生了特殊的動畫效果。

(5)面向程序員。C竭力迎合程序設(shè)計員的需要。它允許用戶訪問硬件,放手讓用戶去操作內(nèi)存中的每個字節(jié)位。C的運算符有多種選擇,使用戶得以簡潔地表達(dá)自己的意見。C在限制用戶方面,不如Pascal那么嚴(yán)格。這既是優(yōu)點,又很危險。說它是優(yōu)點,因為許多工作在C語言里極其簡單;說它危險,因為C使用戶犯一些在其它語言里不可能有的錯誤,C給用戶更多的自由,同時也賦予更大的責(zé)任。1.6

C語言的定義

C語言通常被稱為中級計算機(jī)語言。這并非貶義,也不是說它功能差或難以使用,或者比其它高級語言原始。相反,C語言之所以被稱為中級語言,是因為它把高級語言的最佳元素同匯編語言的強(qiáng)有力的控制結(jié)構(gòu)和靈活性結(jié)合起來了。作為中級語言,C允許對位、字節(jié)和地址這些計算機(jī)功能中的基本成分進(jìn)行操作,因此非常適合編寫經(jīng)常進(jìn)行上述操作的系統(tǒng)程序。盡管如此,C語言程序還是非常容易移植的。所謂可移植指的是,易于把為某種計算機(jī)編寫的軟件改寫到另一種機(jī)器或者操作系統(tǒng)上。例如,為DOS系統(tǒng)寫的一個程序,能夠方便地改為在Windows2000系統(tǒng)下運行。不像高級語言那樣,C幾乎不進(jìn)行運行時的錯誤檢查,例如不檢查數(shù)組邊界是否溢出。檢查運行時的錯誤完全交給程序來處理。1.7

C語言的使用正如前面所述,C是一種編譯型語言。在接下來的章節(jié)中,我們將指導(dǎo)讀者經(jīng)歷從C編程目標(biāo)到最終可執(zhí)行程序的全過程。首先,為了讓讀者對C程序設(shè)計有一個大概的了解,我們把C程序的編寫活動分解成七個步驟。在實際當(dāng)中,特別是針對較大的軟件項目,程序員可能需要在這些步驟之間進(jìn)行反復(fù),利用后續(xù)步驟所學(xué)知識來改進(jìn)前面的步驟。步驟一:確定程序目標(biāo)。不言而喻,程序員打算讓這個程序干什么,在編程的最初就應(yīng)當(dāng)有清晰的思路。對程序所需要的信息、程序所要完成的計算和操作技巧以及程序應(yīng)當(dāng)返回的結(jié)果都應(yīng)當(dāng)有明確的思路。在程序規(guī)劃階段中,應(yīng)當(dāng)概括性地對程序的目標(biāo)有所考量,而不是使用某種特定的計算機(jī)語言來考慮問題。步驟二:設(shè)計程序。一旦對這個程序該做什么有了概念上的描述,下面就要確定程序該如何做。用戶界面應(yīng)該像什么樣子?程序該如何組織?最終用戶是誰?需要多長時間完成?程序員同樣還得決定如何表示程序里的數(shù)據(jù),以及采用哪些方法處理這些數(shù)據(jù)。這在剛開始學(xué)習(xí)C語言編程時,問題都比較簡單,對數(shù)據(jù)的處理也相對簡單。而當(dāng)面臨復(fù)雜問題時,學(xué)習(xí)者會發(fā)現(xiàn)做出這些決策需要更多的思考。選擇一種好的信息表示方法,常常能夠使程序的設(shè)計和數(shù)據(jù)的處理更為容易。同樣在這個階段,我們應(yīng)該用常見的算法表示方法來設(shè)計程序,而不是某種特定的語言代碼。步驟三:編寫代碼。一旦對程序的設(shè)計有了清楚的認(rèn)識,就可以著手編寫代碼去實現(xiàn)。這意味著把程序的設(shè)計翻譯成C語言代碼。這也是真刀真槍地運用C知識的過程。一般而言,程序員使用文本編輯器來創(chuàng)建源代碼(SourceCode)文件。該文件是用戶對程序設(shè)計的C語言再現(xiàn),也是一個C程序生命周期的開始。圖1.16給出的Hello程序是由K&R合著的《TheCProgrammingLanguage》給出的第一個C源程序。圖1.16

Hello程序該源程序可以由程序員通過編輯器創(chuàng)建并保存為文本文件,文件名就是Hello.c。源程序?qū)嶋H上就是由一系列的字節(jié)組成的,每個字節(jié)表示程序中的某個文本字符。采用的具體編碼格式遵循1.2節(jié)的ASCII碼規(guī)則。實際上就是用一個惟一的字節(jié)大小的整數(shù)值來表示每個字符,如圖1.17給出了Hello.c源程序的ASCII表示。圖1.17Hello.c的ASCII碼文本表示在圖1.17中,〈sp〉表示空格,其ASCII值為32。由圖1.17可知,hello.c程序?qū)嶋H上就是以字節(jié)序列的形式保存的磁盤文件,也稱為文本文件。每個字符對應(yīng)一個整數(shù)值。例如第一個字節(jié)的整數(shù)值35對應(yīng)于字符“#”;第二個字節(jié)的整數(shù)值105對應(yīng)于字符“i”。值得注意的是,每一行文本都是以不可見的換行(Newline)字符“\n”結(jié)束,其整數(shù)值為10。

Hello.c文件的這種表示再次說明一個基本的概念:計算機(jī)系統(tǒng)內(nèi)的所有信息都是用比特串的模式來表示的。作為本步驟的組成部分,程序員應(yīng)該為自己所做的編程工作編寫文檔。利用C語言的注釋機(jī)制在源代碼中加入對程序的說明。步驟四:編譯。本步驟是對源代碼進(jìn)行編譯,其具體細(xì)節(jié)依賴于用戶的程序設(shè)計環(huán)境。在此我們只對編譯作一個概念性的討論。

C源程序是用高級編程語言編寫而成的。盡管對程序員來說用高級語言來表示解決問題的方案要來得容易。但是計算機(jī)無法理解其具體含義,也就無法直接執(zhí)行一個C源程序。因此,必須借助其他程序把源代碼中的C語句轉(zhuǎn)換成低級的機(jī)器語言指令序列,才能在計算機(jī)上執(zhí)行。負(fù)責(zé)完成翻譯轉(zhuǎn)換的程序稱為編譯程序或者編譯器。圖1.18顯示了編譯器在高級語言程序的開發(fā)和調(diào)試過程中的作用。圖1.18輸入、編譯、運行高級語言程序首先,編譯器本身也是一個程序,它的任務(wù)就是把文本類型的源程序轉(zhuǎn)換成為二進(jìn)制格式的目標(biāo)程序,也稱為目標(biāo)文件。目標(biāo)程序由計算機(jī)的母語或者機(jī)器語言組成。這種語言包含各種用數(shù)字代碼表示的詳細(xì)指令。如果對Hello.c源程序進(jìn)行編譯,編譯器將創(chuàng)建一個名為Hello.obj的目標(biāo)文件。雖然目標(biāo)文件包含機(jī)器指令,但并非所有指令都是完整的。C語言為軟件開發(fā)人員提供了許多完成特定操作的稱為程序塊的代碼——函數(shù),它們存儲在系統(tǒng)可以訪問的其他目標(biāo)文件中。C程序庫包含大量的標(biāo)準(zhǔn)程序,比如printf()和scanf()輸入/輸出函數(shù)。這些程序可以用于程序員自己編寫的代碼中。鏈接器(Linker)程序把這些預(yù)制的函數(shù)和編譯器所創(chuàng)建的目標(biāo)代碼鏈接起來形成一個完整的可執(zhí)行文件(如Hello.exe),其中包含了計算機(jī)可以理解的代碼,它可以由用戶在計算機(jī)上運行。編譯器也檢查用戶程序語法是否合法。倘若編譯器發(fā)現(xiàn)錯誤,那么它把出錯信息報告給用戶,并且不會生成最終的可執(zhí)行文件。步驟五:執(zhí)行程序。如果Hello.exe僅僅是存儲在用戶的磁盤上,則它不會做任何事。按照慣例,可執(zhí)行文件就是用戶可運行的程序。在包括MS-DOS,UNIX,Linux控制臺在內(nèi)的很多常見環(huán)境下的運行程序,只需要輸入可執(zhí)行文件的名字即可。而在集成開發(fā)環(huán)境中,如微軟的WindowsVC++,允許用戶使用菜單選項或者特殊按鍵來編輯和執(zhí)行C程序。當(dāng)然,這些程序也可以在操作系統(tǒng)中通過雙擊文件或者圖標(biāo)來運行它們。要執(zhí)行它,加載程序必須把全部指令復(fù)制到內(nèi)存,并指示CPU從第一條指令開始執(zhí)行。

Shell就是命令解釋程序,它一直處于等待用戶輸入命令狀態(tài)。當(dāng)我們通過鍵盤輸入“hello”時,命令解釋程序把每個字符讀入寄存器,然后保存到內(nèi)存中,如圖1.19所示。圖1.19從鍵盤讀入hello命令當(dāng)最后按回車鍵時,命令解釋程序就知道我們已經(jīng)輸完整條命令。此時,命令解釋程序就會加載hello可執(zhí)行文件,也就是把hello目標(biāo)文件的代碼和數(shù)據(jù)從磁盤拷貝到內(nèi)存中。通過使用DMA(DirectMemoryAccess)技術(shù),數(shù)據(jù)被直接送入內(nèi)存,而不是通過處理器中轉(zhuǎn),如圖1.20所示。圖1.20把可執(zhí)行文件從磁盤加載到內(nèi)存中一旦hello目標(biāo)文件的代碼和數(shù)據(jù)被加載到內(nèi)存中,處理器開始執(zhí)行hello程序內(nèi)main函數(shù)中的機(jī)器語言指令。這些指令將把字符串“hello,world\n”中的字符挨個送入寄存器文件,并最終顯示在屏幕上,如圖1.21所示。圖1.21從內(nèi)存輸出字符串到顯示器步驟六:程序測試與調(diào)試。程序可以運行,這是一個好兆頭。然而,運行的結(jié)果不正確也是很有可能的。因此,用戶應(yīng)當(dāng)檢查程序是否在做它應(yīng)該做的事情。用戶會發(fā)現(xiàn),自己的程序可能存在某些差錯,即蟲子(Bug)。調(diào)試(Debugging)就是尋找并糾正這些錯誤的過程。程序存在缺陷,這本身就是學(xué)習(xí)語言編程的一個部分,也是一種非常正常的現(xiàn)象,是編程工作所固有的。因此,學(xué)習(xí)語言編程就是要從錯誤提示中不斷地去糾正自己所犯的錯誤。隨著自己編程能力的提高,用戶所犯的錯誤也將變得更加隱蔽和更加難以捉摸。用戶在很多地方都容易出錯,可能是設(shè)計上的錯誤;想法不錯,可是設(shè)計不正確;或許忽略了一個意外的輸入;打字錯誤;括號位置不對等等。幸運的是,編譯器能夠捕獲大多數(shù)的錯誤,而且開發(fā)環(huán)境通常還會提供大量的輔助工具幫助用戶監(jiān)視程序的一舉一動,最終經(jīng)過無數(shù)次的調(diào)試編譯,用戶會得到一個正確的程序。步驟七:程序維護(hù)與更新。當(dāng)程序員為自己或者其他人創(chuàng)建了一個程序,這個程序可能得到了廣泛的使用。倘若的確如此,那么程序員大概會有各種各樣的理由去修改它。這或許是因為程序還存在一個細(xì)小的缺陷;也許,是程序員想出了一種更好的解決方法來完成程序中的某個功能;或者是為程序添加一個新的功能;或者是需要把程序移植到不同的計算機(jī)系統(tǒng)。所有這些任務(wù),如果是在程序有非常清晰的、完整的文檔和遵循合理的設(shè)計原則下,那么,實現(xiàn)起來將會簡單得多。程序設(shè)計并不總是像我們剛才所述的那樣是一個線性系統(tǒng)。有的時候,用戶將不得不在各個步驟之間來回反復(fù)。讀者大多具有輕視步驟一(確定程序目標(biāo))和步驟二(設(shè)計程序)的傾向,直接進(jìn)入步驟三(編寫代碼)。讀者最初編寫的程序都很簡單,以至于可以在頭腦里想象出整個過程,一旦發(fā)生錯誤,也容易查清。當(dāng)程序逐漸變大、變復(fù)雜時,思維的可視性開始失效,錯誤隨之難以查找。最后,當(dāng)忽略計劃步驟的用戶編寫出晦澀難懂的、功能惡化的程序時,就要浪費很多時間,才能讓程序從混亂狀態(tài)中恢復(fù)正常。1.8C程序舉例1.8.1舉例1:HelloWorld為了表示對C語言設(shè)計人員的敬意,我們介紹的第一個程序來自經(jīng)典的C著作——《TheCProgrammingLanguage》,由BrianKernighan和DennisRitchie撰寫。該程序的名字為“HelloWorld”,幾乎是所有的學(xué)習(xí)C語言編程的人都會碰到的、一個無處不在的程序。程序本身(源代碼)是作為一個文件保存在計算機(jī)系統(tǒng)的永久性存儲器(如硬盤、U盤)當(dāng)中的。文件的名字可以是Hello.c,其中后綴.c表示這是一個C程序文件。如圖1.22所示,Hello.c程序由三個部分組成:注釋、庫文件包含和主程序。盡管該程序的功能極其簡單,就是在屏幕上打印輸出"Hello,World"字符串,但是,Hello.c程序的結(jié)構(gòu)非常有代表性,在后續(xù)的程序舉例中,讀者甚至?xí)l(fā)現(xiàn),完全可以把它作為一種C程序的開發(fā)模版或者開發(fā)原型來使用。圖1.22hello.c程序

1.注釋

Hello.c的第一部分是英語注釋,描述了程序的基本功能。在C語言中,只要是包含在“/*”和“*/”這一對標(biāo)記內(nèi)的所有的文字都被認(rèn)為是注釋(Comment)。注釋可以跨越多行,例如,上述Hello.c程序的注釋總共有八行。注釋除了不能出現(xiàn)在關(guān)鍵詞、變量名和函數(shù)名字的中間以外,它幾乎可以出現(xiàn)在程序的任何地方。但是,在C語言中,注釋不能出現(xiàn)在其他注釋當(dāng)中,即注釋不能嵌套(Nested)。這也就意味著注釋當(dāng)中不能再有其它注釋。一旦編譯器發(fā)現(xiàn)開始標(biāo)志“/*”,它就忽略后續(xù)的任何字符,直到碰到結(jié)束標(biāo)志“*/”。因此,以下注釋行/*==========/*@@@@@@@@@*/=========*/是無效的和非法的,會導(dǎo)致編譯出錯。注釋是為不同的計算機(jī)用戶編寫的,而不是為計算機(jī)編寫的。它們主要是對源代碼的用途和含義進(jìn)行說明,以利于用戶在一段時間后,再回過頭來閱讀這些代碼時能更好地記得和理解它們。這可以幫助編程人員和其他用戶理解程序的功能和操作,也有助于對程序的調(diào)試和測試。注釋不影響程序的執(zhí)行速度以及編譯后程序的大小,我們應(yīng)盡可能在需要的地方對程序進(jìn)行注釋。C編譯器在把源代碼翻譯成可執(zhí)行程序時,簡單地忽略所有的程序注釋。因此,用戶也可以用注釋臨時移除一行代碼,只要把這行代碼用注釋符號圍起來即可。

2.庫文件包含程序的第二部分包含以下代碼行:

#include<stdio.h>這行代碼表示程序需要使用C語言提供的標(biāo)準(zhǔn)函數(shù)庫(Library)。庫是完成某些特定操作的函數(shù)集合。Hello.c程序使用的庫是一個標(biāo)準(zhǔn)的輸入/輸出庫(stdio是standardinput/output的縮寫)。如果用戶的程序需要使用其他的C語言提供的函數(shù),只要用命令#include把它包含進(jìn)來即可。庫的使用可以減輕編程人員的負(fù)擔(dān),提高軟件的開發(fā)效率。讀者很快會發(fā)現(xiàn),幾乎所有的程序或多或少地需要使用各種庫函數(shù)。以.h結(jié)尾的文件我們通常稱為頭文件(HeaderFile)。有關(guān)頭文件的內(nèi)容將在后續(xù)章節(jié)進(jìn)行詳細(xì)討論。

3.主程序

Hello.c文件的最后一部分是程序本身,包含以下代碼行:

main()

{

printf("Hello,World.\n");

}這四行代碼組成了C語言的第一個函數(shù)的例子。這個函數(shù)就是C語言的主函數(shù)——main()函數(shù)。所謂函數(shù),指的是有機(jī)組合的單個程序步驟的序列,并給這些序列賦予一個名字,就是函數(shù)的名字。在此例當(dāng)中,函數(shù)的名字就是第一行給出的main,通常也是所有C程序的標(biāo)準(zhǔn)開頭。函數(shù)要執(zhí)行的步驟則被列于一對花括號之間,通常稱為語句(Statement)。每條語句都必須以分號結(jié)束??梢哉f,語句組成了函數(shù)的執(zhí)行體。Hello.c程序的main()函數(shù)只包含一條語句。每次用戶在執(zhí)行一個C程序時,計算機(jī)首先執(zhí)行main()函數(shù)內(nèi)的各條語句。因此main()函數(shù)是惟一一個必須在C程序內(nèi)出現(xiàn)的函數(shù),且只能有一個main()函數(shù)。在Hello.c程序中,main函數(shù)內(nèi)只包含一條語句:

printf("Hello,World.\n");這條語句使用了標(biāo)準(zhǔn)輸入/輸出庫當(dāng)中的printf()函數(shù)。要使用這個函數(shù)必須在程序的開頭部分加入以下代碼:

#include<stdio.h>

printf和main一樣,都是函數(shù)的名字,都表示特定的操作序列。要完成這些操作序列,只要直接使用各自的函數(shù)名即可。在編程環(huán)境下,使用名字來引用函數(shù)的行為被稱為函數(shù)的調(diào)用(Call),因此,下列語句

printf("Hello,World.\n");表示調(diào)用printf()函數(shù)。在調(diào)用函數(shù)時,除了需要有函數(shù)名字表示要執(zhí)行什么操作以外,通常還需要提供額外的一些信息。例如,printf()的功能是在屏幕上顯示數(shù)據(jù),那這些數(shù)據(jù)是什么呢?在C語言中,這些額外的數(shù)據(jù)是通過函數(shù)名后面的括號當(dāng)中的參數(shù)(Argument)列表來提供的。這些參數(shù)所提供的信息可以被函數(shù)所使用。在printf()函數(shù)中,只有一個參數(shù),就是字符序列,或者稱為字符串,它們用雙引號括起來,如下:

"Hello,World.\n"這個字符串就是提供給printf()函數(shù)的數(shù)據(jù),它們將最終顯示在計算機(jī)屏幕上。對于這個惟一的參數(shù),printf()函數(shù)負(fù)責(zé)依次顯示H,e,l等字符,直到整條消息都出現(xiàn)在屏幕上為止,如下:

Hello,World.字符串的最后一個字符“\n”是一個特殊字符,稱為換行符(newline)。當(dāng)printf()函數(shù)碰到一個換行符,屏幕上的光標(biāo)就會移到下一行的開始,正如在鍵盤上按回車鍵(Return)的效果。在

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論