1.4 C語言的初步知識
1.4.1 C語言的起源與發(fā)展
C語言誕生于1972年,由美國電話電報公司(AT&T)貝爾實驗室的D.M.Ritchie設(shè)計,并首先在一臺使用UNIX操作系統(tǒng)的DEC PDP-11計算機上實現(xiàn)。
C語言是在B語言的基礎(chǔ)上發(fā)展起來的,早在1970年,美國貝爾實驗室的K.Thompson就以BCPL語言(Basic Combined Promgramming Language)為基礎(chǔ),設(shè)計出一種既簡單又接近于硬件的B語言,并用它編寫了第一個UNIX操作系統(tǒng)。而BCPL語言是英國劍橋大學(xué)的Matin Richards于1967年基于CPL語言(Combined Programming Language)提出的一種改進語言。CPL語言又是英國劍橋大學(xué)于1963年根據(jù)ALGOL 60 推出的一種接近硬件的語言。由此可見,C語言的根源可以追溯到ALGOL 60,其演變過程如下:
ALGOL 60(1960年)→CPL(1963年)→BCPL(1967年)→B(1970年)→C(1972年)
C 語言問世以后,在應(yīng)用中多次進行了改進。1973年貝爾實驗室的 K.Thompson 和D.M.Rithie用C語言將UNIX系統(tǒng)(即UNIX第5版)重寫了一遍,增加了多道程序設(shè)計功能,使整個系統(tǒng),包括C語言的編譯程序都建立在C語言的基礎(chǔ)上。第5版UNIX系統(tǒng)(UNIX V5)奠定了UNIX系統(tǒng)的基礎(chǔ)。到1975年,UNIX第6版問世。隨著UNIX的巨大成功和被廣泛移植到各種機器上,C 語言也被人們所接受,并移植到大型、中型、小型和微型機上,它很快風(fēng)靡全世界,成為世界上應(yīng)用最廣泛的計算機程序設(shè)計語言之一。
1978年又推出了UNIX第7版,以該版本中的C語言編譯程序為基礎(chǔ),B.W.Kernighan和D.M.Ritchie合作(被稱為K&R)出版了“The C Programming Language”一書。該書介紹的C語言被稱為標(biāo)準(zhǔn)C,這本書成為后來被廣泛使用的C語言的基礎(chǔ)。1983年,美國國家標(biāo)準(zhǔn)化協(xié)會(ANSI)對C語言的各種版本做了擴充和完善,推出了新的標(biāo)準(zhǔn),被稱為ANSI C,它比原來的標(biāo)準(zhǔn)C有了很大的改進和發(fā)展。1987年,ANSI又公布了87 ANSI C新版本。目前流行的各種C語言編譯系統(tǒng)都是以87 ANSI C為基礎(chǔ)的。在微機上使用的C語言編譯系統(tǒng)多為Microsoft C、Turbo C、Borland C和Quick C等,它們略有差異,但按標(biāo)準(zhǔn)C書寫的程序,基本上都可運行。讀者要了解不同版本的編譯系統(tǒng)的特點和規(guī)定可參閱有關(guān)手冊。
1.4.2 C語言的特點
C 語言之所以成為世界上應(yīng)用最廣泛、最受人們喜愛的計算機高級語言之一,與它本身所具有的突出的優(yōu)點是分不開的。C語言的主要特點概括如下。
① 語言簡潔、緊湊,使用方便、靈活。C語言一共只有32個關(guān)鍵字,9種控制語句。程序書寫形式自由,主要用小寫字母表示。
② 支持結(jié)構(gòu)化程序設(shè)計。C語言具有結(jié)構(gòu)化的控制語句,以函數(shù)作為程序的模塊單位,這使得它可以很方便地實現(xiàn)這種構(gòu)造。
③ 運算符豐富。C語言除了擁有一般高級語言都有的運算符外,還擁有不少獨特的運算符,可以實現(xiàn)其他高級語言不能實現(xiàn)的運算,增強了C語言的運算功能。
④ 數(shù)據(jù)類型豐富。C 語言能方便地實現(xiàn)各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu),具有很強的數(shù)據(jù)處理能力。
⑤ 較強的編譯預(yù)處理功能。C語言的編譯預(yù)處理功能,為開發(fā)規(guī)模較大的程序提供了方便,極大地提高了程序開發(fā)的效率。
⑥ C語言的可移植性好。C語言本身只需稍加修改便可用于各種型號的計算機和各類操作系統(tǒng),因此,用C語言編寫的程序也可以很方便地用于不同的系統(tǒng),這也是C語言得以廣泛應(yīng)用的原因之一。
⑦ C語言本身既有一般高級語言的優(yōu)點,又有低級(匯編)語言的特點。C語言可以允許直接訪問內(nèi)存地址,可以進行位(bit)運算,也可以直接對機器硬件進行操作。因此,既可以用它來編寫大型系統(tǒng)軟件,也可以用它編寫各種應(yīng)用軟件,許多以前只能用匯編語言處理的問題,現(xiàn)在可以改用C語言處理了。
⑧ 語法限制不太嚴(yán)格,程序設(shè)計自由度大。C語言由于放寬了語法檢查,使程序員有較大的自由度。例如,對數(shù)組下標(biāo)越界不做檢查,要由程序設(shè)計人員自己保證其正確性。因此,用C語言編寫程序,對程序設(shè)計人員的要求相應(yīng)地就要高一些。
上述C語言的特點,在初學(xué)時也許還不能深刻理解,待學(xué)完C語言之后就會有比較深的體會和感受。
1.4.3 C語言程序的構(gòu)成
下面通過兩個簡單的C語言程序,使大家能夠?qū)語言程序有一個最基本的認(rèn)識。
【例1.4】 求兩個整數(shù)m與n的和。
程序中,m和n分別表示兩個整數(shù),sum表示兩個整數(shù)的和。
程序代碼如下:
#include "stdio.h"
main() /* 主函數(shù) */
{
int m,n,sum; /* 定義變量m,n,sum */
m=5;n=3; /* 給變量m,n賦值 */
sum=m+n; /* 求m+n的值,并賦給變量sum */
printf("sum is %d\n",sum); /* 輸出sum的值 */
}
以上程序由一個稱為主函數(shù)的main( )函數(shù)構(gòu)成。C語言規(guī)定必須用main作為主函數(shù)名,其后的一對圓括號“( )”中間可以是空的,但這一對圓括號不能省略。主函數(shù)后面是函數(shù)體,由一對大括號“{ }”括起來,左大括號“{”表示函數(shù)體開始,右大括號“}”表示函數(shù)體結(jié)束。“/* …… */”表示注釋部分,它只是起到幫助閱讀程序的作用,對編譯和運行不產(chǎn)生任何影響。為方便理解,可采用漢字來注釋,注釋部分可以出現(xiàn)在程序的任何地方。程序第4行是變量定義語句,定義m、n和sum為整型(int)變量;程序第5行是兩條賦值語句,使m和n的值分別為5和3;程序第6行也是一條賦值語句,使sum的值為表達式m+n的值;程序第7行是輸出語句,其中,printf( )是C語言的標(biāo)準(zhǔn)輸出函數(shù)(當(dāng)引用C語言的標(biāo)準(zhǔn)函數(shù)時,需在程序開始處使用文件包含命令將該函數(shù)所對應(yīng)的頭文件包含進來。本程序第1行就是文件包含命令,它將標(biāo)準(zhǔn)輸入/輸出函數(shù)的頭文件stdio.h包含進來了。關(guān)于文件包含的知識將在第 7 章介紹),雙引號中的%d 表示在此位置以十進制整數(shù)類型輸出變量 sum的值,\n 為回車換行符,雙引號中其他內(nèi)容將作為字符串原樣輸出。因此,該程序的運行結(jié)果如下:
sum is 8
【例1.5】 求兩個整數(shù)中的較小者。
程序中,x、y分別表示兩個整數(shù),min表示兩個整數(shù)之中的較小值。
程序代碼如下:
#include "stdio.h"
main() /* 主函數(shù) */
{
int x,y,min; /* 定義變量 */
int fun(int a,int b); /* 當(dāng)定義的函數(shù)在主函數(shù)之后時,要進行函數(shù)的聲明 */
printf("input x,y:"); /* 提示輸入數(shù)據(jù) */
scanf("%d,%d",&x,&y); /* 通過鍵盤輸入變量x和y的值 */
min=fun(x,y); /* 調(diào)用fun函數(shù),將函數(shù)值賦給min */
printf("min=%d\n",min); /* 輸出min的值 */
}
int fun(int a,int b) /* 定義fun函數(shù),值為整型,a和b為該函數(shù)的形式參數(shù) */
{
int c; /* 函數(shù)中用到的變量c也要定義 */
if(a<b) c=a;
else c=b;
return(c); /* 將c的值返回至調(diào)用處 */
}
該程序包括兩個函數(shù):主函數(shù)main( )和用戶自定義函數(shù)fun( )。主函數(shù)的第7行是輸入語句。scanf( )是C語言的標(biāo)準(zhǔn)輸入函數(shù),它的作用是讓用戶從鍵盤上輸入數(shù)據(jù);雙引號中的兩個%d是格式說明,表示用戶輸入的數(shù)據(jù)應(yīng)該是兩個整數(shù);&x和&y中&的含義是取地址,它表示用戶從鍵盤上輸入的兩個整數(shù)將分別送到變量x和y所對應(yīng)的存儲單元中,也就是輸入給變量x和y。第8行是調(diào)用fun( )函數(shù), 調(diào)用時將x和y的值傳送給被調(diào)函數(shù)fun( )中的形參a和b,在被調(diào)函數(shù)fun( )中,求出兩個數(shù)中的較小值賦給變量c, 最后由return語句返回c的值到主調(diào)函數(shù)main( )中的調(diào)用處,并將返回的值送給變量min。
該程序的運行情況如下:
input x,y:10,2<Enter>
min=2
以上兩例中,關(guān)于標(biāo)準(zhǔn)輸入/輸出函數(shù)的使用、函數(shù)調(diào)用、實參和形參的概念,大家可能還不十分清楚,可以先不予以深究,今后在有關(guān)章節(jié)中還要詳細介紹。分析上述程序可以總結(jié)出C語言程序的基本構(gòu)成如下。
(1)C語言程序由函數(shù)構(gòu)成
一個C語言程序至少應(yīng)包含一個main( )函數(shù)(如例1.4),或者包含一個main( )函數(shù)和若干個用戶自定義函數(shù)(如例1.5)。因此,函數(shù)是C語言程序的基本單位,相當(dāng)于其他語言的子程序或過程。
C語言的函數(shù)可以分為系統(tǒng)提供的標(biāo)準(zhǔn)函數(shù)(庫函數(shù),如例1.5中的printf( )和scanf( )函數(shù))和用戶自定義函數(shù)(如例1.5中的fun( )函數(shù))。各種C語言的編譯系統(tǒng)所提供的標(biāo)準(zhǔn)函數(shù)的數(shù)量和功能以及函數(shù)名都不完全相同,標(biāo)準(zhǔn)C提供了100多個標(biāo)準(zhǔn)函數(shù),函數(shù)調(diào)用使C語言很容易實現(xiàn)程序的模塊化。
為了增加程序的可讀性,可以用“/*……*/”在任何位置上對 C 語言程序的任何部分作注釋,一般在一個程序或函數(shù)的開始或某些程序的難點之處加上必要的注釋(在VC++6.0環(huán)境下也可使用符號“//……”引出注釋)。
(2)一個C語言函數(shù)通常由兩部分組成:函數(shù)的首部和函數(shù)體
函數(shù)的首部包括函數(shù)類型、函數(shù)名、一對圓括號、函數(shù)參數(shù)(形參)名和參數(shù)類型的說明。比如,例1.5中fun( )函數(shù)的首部如圖1.9所示。
注意:C 語言規(guī)定,一個函數(shù)名后面必須緊跟一對圓括號,函數(shù)的所有形參都必須寫在括號內(nèi)。如果函數(shù)沒有形參,則括號內(nèi)可以是空的,但不能省略圓括號,例如,主函數(shù)main( )經(jīng)常不帶參數(shù)。
函數(shù)體就是函數(shù)首部后面一對花括號{}內(nèi)的部分。如果一個函數(shù)內(nèi)有多對花括號,則最外面的一對花括號{}所包含的內(nèi)容就是該函數(shù)的函數(shù)體。函數(shù)體一般包括說明部分和執(zhí)行部分。
① 說明部分
說明部分由若干條變量定義語句或函數(shù)聲明語句組成。C 語言規(guī)定,函數(shù)中使用的所有變量(或數(shù)組)必須在使用前進行定義,否則會在編譯時出錯。如例1.5中main( )函數(shù)的變量定義語句“int x,y,min;”。當(dāng)然也可以沒有說明部分。例如下面的程序代碼:
main( )
{ printf("It is fine today!");}
該程序的作用是在屏幕上顯示以下文字:
It is fine today!
這里沒有用到任何變量,所以不需要變量的定義。
② 執(zhí)行部分
執(zhí)行部分由若干條執(zhí)行語句組成。程序的功能就是通過執(zhí)行部分實現(xiàn)的。C 語言的任何語句都必須以分號“;”結(jié)束,分號是C語句的必要組成部分。例如:
y=x+b;
C 語言的語句可以從任意位置開始書寫,書寫格式自由,一行內(nèi)可以寫多條語句,語句中多個空格與一個空格等效。
一個函數(shù)甚至可以既無說明部分,也無執(zhí)行部分,例如:
comp( )
{}
這個函數(shù)是一個空函數(shù),什么作用也沒有,但卻是合法的。
(3)main( )函數(shù)
一個C語言的程序總是從main( )函數(shù)開始執(zhí)行,并終止于main( )函數(shù),而不論main( )函數(shù)在整個程序中處于什么樣的位置(main( )函數(shù)可以放在程序的開頭、最后,或某兩個函數(shù)之間)。但是,為便于理解,通常將main( )函數(shù)放在程序的開頭或最后。
1.4.4 C語言程序的上機調(diào)試過程
如何調(diào)試一個C語言程序呢?在不同的環(huán)境下調(diào)試的方法稍有差異(在VC++6.0環(huán)境下C語言程序的調(diào)試過程請參見本教材實驗篇中的實驗一)。但歸納起來一般是依照圖1.10所示的過程調(diào)試的。
從圖1.10可以看出,C語言程序的調(diào)試過程基本上可以分為以下4步。
1.編輯
編輯就是用C語言寫出源程序。其方法有兩種:一種是使用文本編輯程序?qū)⒃闯绦蜉斎胗嬎銠C,經(jīng)修改認(rèn)為無誤后,以.c 為后綴存入文件系統(tǒng)(C 源程序的后綴一般定為“.c”)中;另一種是使用 C 語言編譯系統(tǒng)提供的編輯器將源程序輸入計算機,并且存入文件系統(tǒng)中。例如在圖1.10中,某用戶將自己的源程序文件定名為file.c。
2.編譯
調(diào)用C語言編譯程序?qū)υ次募M行編譯,即檢查其詞法、語法、語義方面是否存在錯誤。
通俗點說,就是檢查是否有拼錯的關(guān)鍵詞,是否有不符合C語言語法規(guī)則的表達式及語義方面的矛盾和含混。這些錯誤在編譯階段都可以查出。
如果有錯誤,則系統(tǒng)將顯示“錯誤信息”。用戶根據(jù)指出的錯誤信息,對源程序進行編輯修改,修改后再重新進行編譯,直到編譯無誤為止。編譯后生成的機器指令程序,被稱為目標(biāo)程序,此目標(biāo)程序名與相應(yīng)的源程序同名,但其后綴為.obj 。上述源程序文件file.c經(jīng)編譯后得到目標(biāo)程序file.obj。
3.連接
編譯產(chǎn)生的目標(biāo)文件一般不能直接運行,必須把它所引用的標(biāo)準(zhǔn)函數(shù)及源程序指定的目標(biāo)文件一起裝配連接起來,形成完整的可執(zhí)行文件。一般可執(zhí)行文件名與源程序文件名同名,后綴為.exe。例如,上述源程序文件file.c經(jīng)編譯連接后得到可執(zhí)行文件file.exe。
4.執(zhí)行程序
當(dāng)程序編譯連接后,生成可執(zhí)行程序便可以運行了,以后用戶只需輸入可執(zhí)行目標(biāo)文件名即可,例如:
file<Enter>