語言的數(shù)據(jù)結(jié)構(gòu)教學課件_第1頁
語言的數(shù)據(jù)結(jié)構(gòu)教學課件_第2頁
語言的數(shù)據(jù)結(jié)構(gòu)教學課件_第3頁
語言的數(shù)據(jù)結(jié)構(gòu)教學課件_第4頁
語言的數(shù)據(jù)結(jié)構(gòu)教學課件_第5頁
已閱讀5頁,還剩135頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

機器語言計算1+1101110000000000100000000000001010000000100000000匯編語言MOVAX,1101110000000000100000000ADDAX,1000001010000000100000000BASIC語言PRINT1+1C語言#include<stdio.h>main(){ printf("%d\n",1+1);}C語言的創(chuàng)世紀一切從一個叫“SpaceTravel”的電子游戲開始……為了讓他的游戲能在PDP-7上運行,KenThompson用匯編語言給PDP-7寫了一個操作系統(tǒng)——UNIX匯編太不好用了,Thompson需要高級語言試驗了一些高級語言,包括Fortran,都不理想他在BCPL基礎上,自己設計了一個B語言UNIX開始發(fā)展,B也不夠用了DennisRitchie加入,把B改造成C開始用C重寫UNIXRitchie和Thompson在開發(fā)UNIX接受美國國家技術(shù)勛章C程序設計語言是一種高級語言高級語言并不是“高級”,只是相對低級語言,在一個高的級別上進行編程歷史悠久,戰(zhàn)勛卓著誕生于上世紀70年代初,成熟于80年代(C89),修訂與90年代(C99)很多重量級軟件都是用C寫的上天入地,無所不能幾乎沒有不能用C寫出來的軟件,沒有不支持C的系統(tǒng)很多流行語言、新生語言都借鑒了它的思想、語法從C++,到Java,再到C#,還有php等C語言的祖師爺

DennisM.Ritchiecs.bell-labs/who/dmr//Ritchie漫畫像Cisquirky,flawed,andanenormoussuccess.計算機基本工作過程整個過程的執(zhí)行者是硬件,但硬件是受軟件控制的編程,就是編寫軟件,使硬件按照人的意圖工作編譯運行編譯過程程序員(Programmer)編寫程序源代碼(SourceCode)編譯器(Compiler)把源代碼轉(zhuǎn)換為可被計算機理解的機器代碼(MachineCode),并把機器代碼以可執(zhí)行文件(ExecutableFile)的形式保存在磁盤上軟件的運行計算機把機器代碼讀入到內(nèi)存(Memory),由CPU運行這些代碼,讀取輸入(Input),產(chǎn)生輸出(Output),完成程序員預定的功能編譯語言一種編譯語言對應一種編譯器程序員按照該語言的語法編寫程序源代碼,把自己的意圖融入到代碼中編譯器讀入源代碼,把程序員的意圖轉(zhuǎn)換成可執(zhí)行程序,供他人使用C語言可執(zhí)行程序編譯器解釋運行解釋運行過程程序員編寫程序源代碼解釋器讀入源代碼,并執(zhí)行源代碼解釋運行的語言特點執(zhí)行速度慢好學易用先編譯、后解釋把源代碼編譯成更容易解釋的中間代碼,然后再解釋運行C程序設計語言第1章觀其大略Hello,World#include<stdio.h>main(){ printf("hello,world\n");}超級無敵考考你:

如何把“hello”和“world”分別打印在兩行?hello.c打印華氏溫度與攝氏溫度對照表計算公式:

C=(5/9)(F-32)打印華氏溫度與攝氏溫度對照表#include<stdio.h>/*對fahr=0,20,...,300

打印華氏溫度與攝氏溫度對照表*/main(){

int

fahr,celsius;

int

lower,upper,step;

lower=0;/*溫度表的下限*/

upper=300;

/*溫度表的上限*/

step=20;/*步長*/

fahr

=lower;

while(fahr<=upper){

celsius=5*(fahr-32)/9;

printf("%d\t%d\n",fahr,celsius);

fahr=fahr+step;

}}fc1.c代碼風格#include<stdio.h>/*對fahr=0,20,...,300

打印華氏溫度與攝氏溫度對照表*/main(){

int

fahr,celsius;

int

lower,upper,step;

lower=0;/*溫度表的下限*/

upper=300;

/*溫度表的上限*/

step=20;/*步長*/

fahr

=lower;

while(fahr<=upper){

celsius=5*(fahr-32)/9;

printf("%d\t%d\n",fahr,celsius);

fahr=fahr+step;

}}fc1.c更簡單、精確的對照表打印程序#include<stdio.h>#defineLOWER0/*表的下限*/#defineUPPER300/*表的上限*/#defineSTEP20/*步長*//*打印華氏-攝氏溫度對照表*/main(){

intfahr;

for(fahr=LOWER;fahr<=UPPER;fahr=fahr+STEP) printf("%3d#%6.1f\n", fahr, (5.0/9.0)*(fahr-32));}fc2.c字符輸入輸出c=getchar()從鍵盤讀入一個字符,賦值給變量cputchar(c)把c輸出到屏幕拷貝的基本思想:

讀一個字符

while(該字符不是文件結(jié)束指示符)

輸出剛讀進的字符

讀下一個字符拷貝(Copy)#include<stdio.h>/*用于將輸入復制到輸出的程序;第1個版本*/main(){

intc;

c=getchar();

while(c!=EOF){ putchar(c); c=getchar(); }}copy1.c一個更好的版本#include<stdio.h>/*用于將輸入復制到輸出的程序;第2個版本*/main(){

intc; while((c=getchar())!=EOF) putchar(c);}copy2.c計算行數(shù)#include<stdio.h>/*統(tǒng)計輸入的行數(shù)*/main(){ intc;

longnl; nl=0;

while((c=getchar())!=EOF) {

if(c=='\n') nl++; } printf("%d\n",nl);}counter.c加法器#include<stdio.h>/*計算輸入的兩個整數(shù)的和*/main(){

inta,b; printf("Pleaseinputtwointegers:"); scanf("%d%d",&a,&b); printf("Sum=%d\n",a+b);}add.c平均分#include<stdio.h>/*計算某科成績的平均值*/#defineTOTAL_NUMBER10/*總?cè)藬?shù)*/main(){

floatsum=0,score[TOTAL_NUMBER];

inti; printf("Input%dscores:\n",TOTAL_NUMBER);

for(i=0;i<TOTAL_NUMBER;i++) { scanf("%f",&score[i]); sum=sum+score[i]; } printf("Average=%f\n",sum/TOTAL_NUMBER);}average.c函數(shù)(Function)前面使用了系統(tǒng)提供的函數(shù):printf,scanf,getchar,putchar使用函數(shù)時,我們不用知道這個函數(shù)內(nèi)部是如何運作的,只按照我們的需要和它的參數(shù)形式調(diào)用它即可我們也可以定義自己的函數(shù)“一個程序應該是輕靈自由的,它的函數(shù)就象串在一根線上的珍珠。”(《編程之道》)power函數(shù)/*power:求底的n次冪;n>=0*/intpower(intbase,intn){ inti,p;

p=1;

for(i=1;i<=n;++i) p=p*base;

returnp;}power.cpower函數(shù)的調(diào)用(Call)#include<stdio.h>intpower(intbase,intn);/*測試power函數(shù)*/main(){

intm,n; m=power(2,1); n=power(-3,3); printf("%d%d\n",m,n);

return0;}power.c這一章我們學到了#include<stdio.h>#definemain()printf(),scanf()getchar(),putchar()<=,>=,==,!=int,long,float數(shù)組while,for,if代碼風格注釋、縮進、空行、命名……函數(shù)C程序設計語言第2章類型、運算符與表達式標識符(Identifiers)用戶自定義的符號叫標識符如變量名、函數(shù)名、宏和類型名標識符由字母、數(shù)字和下劃線組成,大小寫敏感不可以是數(shù)字開頭標識符要直觀,能表達它的功能下劃線和大小寫通常用來增強可讀性variablenamevariable_name,VARIABLE_NAMEVariableName,variableName關鍵字(keyword)不可作為標識符int,float,for,while,if等(教材164頁)某些功能的變量采用習慣命名如:for語句所采用的循環(huán)變量習慣用i,j,k基本數(shù)據(jù)類型(DataType)int整數(shù),在目前絕大多數(shù)機器上占4個字節(jié)TC2中是2個字節(jié)所占字節(jié)數(shù)取決于機器字長float單精度浮點數(shù),一般是4個字節(jié)長double雙精度浮點數(shù),一般是8個字節(jié)長char字符,一般是1個字節(jié)長用來表示256個ASCII字符,或者0~255的整數(shù)數(shù)據(jù)類型修飾符shortshort

int,短整數(shù),一般2個字節(jié)長。通常簡寫為shortlonglong

int,長整數(shù),一般是4個字節(jié)長。通常簡寫為longlong

double,高精度浮點數(shù),一般是10個字節(jié)長。signed用來修飾char、int、short和long,說明他們是有符號的整數(shù)(正整數(shù)、0和負整數(shù))。一般缺省都是有符號的,所以這個修飾符通常省略unsigned用來修飾char、int、short和long,說明他們是無符號的整數(shù)(正整數(shù)和0)超出取值范圍會怎樣?TC2中int的范圍是-32767~32767如果我們給它一個小于-32767或者大于32767的數(shù)會如何呢?現(xiàn)場編程測驗……小蛇能吞下大象嗎?溢出(Overflow)造成的危害一臺安裝了Windows95/98的機器,如果連續(xù)運行49.7天沒有重新啟動,可能死機原因:Windows自啟動時刻起,有一個計數(shù)器,記錄系統(tǒng)已經(jīng)運行了多少毫秒。這個計數(shù)器是個unsigned

long類型的變量unsigned

long的最大值是:4294967295一天有24*60*60*1000=86400000毫秒4294967295/86400000=49.71026961805……當49.7天的時候,此計數(shù)器會溢出,引起死機浮點數(shù)的陷阱#include<stdio.h>main(){

floatf; f=123.456;

if(f==123.456) printf("fisequalto123.456indeed.");

else printf("Infact,fisequalto%f\n",f);}運行結(jié)果會是什么?float.c浮點數(shù)的陷阱float的精度低,較易發(fā)生精度帶來的相等性判斷問題double精度高,這個問題發(fā)生的概率小一些,但也存在解決辦法:

if(fabs(f–123.456)<1E-5)

……根據(jù)精度要求設定使用變量要注意不要對變量所占的字節(jié)數(shù)想當然用sizeof獲得變量或者數(shù)據(jù)類型的長度用ANSIC定義的宏確定數(shù)據(jù)的表示范圍,解決溢出問題sizeof.c常數(shù)(Constant)整型常數(shù)123、456123456123l、123L、123456l、123456L浮點常數(shù)123.45、456.781e-2、4.5e3123.45f、456.78F、1e-2f、4.5e3F123.45l、456.78L、1e-2l、4.5e3L八進制與十六進制常數(shù)以數(shù)字“0”開始的整型常數(shù)是八進制數(shù)010和10大小不一樣因為八進制并不常用,所以此種表示法比較少見,因而常被用錯以“0x”或者“0X”開始的整型常數(shù)是十六進制A~F和a~f用來表示十進制的10~150x11,0x05,0xFA,0xFF十六進制的形式比較常用,尤其在進行位一級的控制的時候字符常數(shù)字符常數(shù)的表示方法'a','A','5','%','$'……單引號內(nèi)只能有一個字符,除非用“\”開頭就是一個普通整數(shù),也可以參與各種數(shù)學運算每個字符具有一個0~255之間的數(shù)值,可從ASCII表查出注意:'5'和5的區(qū)別,A和'A'的區(qū)別字符的數(shù)學運算在密碼學內(nèi)用得比較多ascii.c字符常數(shù)轉(zhuǎn)義字符一些特殊字符(無法從鍵盤輸入或者在C語言里有它用)用轉(zhuǎn)義字符表示轉(zhuǎn)義的思想在網(wǎng)絡協(xié)議和文件格式中經(jīng)常使用字符串(String)常數(shù)用雙引號括住的由0個或多個字符組成的字符序列"Iamastring"""表示空字符串轉(zhuǎn)義字符也可以在字符串中使用引號只作為字符串開始和結(jié)束的標志C語言內(nèi)部用'\0'表示字符串的結(jié)束除注釋外,是唯一可以出現(xiàn)中文的地方"x"和'x'是不同的<string.h>里定義了一系列專門的字符串處理函數(shù)枚舉(Enumeration)常數(shù)一個幾乎被遺忘的角色從程序來窺其一斑

enumweeks{MON,TUE,WED,THU,FRI,SAT,SUN};

enumweekstoday,tomorrow;

today=MON;tomorrow=today+1;

if(tomorrow==TUE)printf("TomorrowisTuesday.\n");

elseprintf("TomorrowisNOTTuesday.\n");enum.c變量聲明變量必須“先定義,后使用”所有變量必須在第一條可執(zhí)行語句前定義聲明的順序無關緊要一條聲明語句可聲明若干個同類型的變量,變量名之間用逗號分隔變量定義后,即占用內(nèi)存,可向其存入各種數(shù)據(jù),并可通過變量名使用數(shù)據(jù)聲明變量,是初始化變量的最好時機不被初始化的變量,其值為危險的隨機數(shù) charesc='\\'; inti=0; intlimit=MAXLINE+1; floateps=1.0e-5;常量用const修飾定義的變量為常量const

inti=0;常量只能在定義時賦值,然后不能再改變其值常數(shù)、常量、宏和枚舉,都可以用來表示一個永遠不會改變的數(shù)前者不建議直接使用,而用后三者代替后三者的工作機理是完全不同的,達到的效果也不盡相同計算機只會計算任何事物都要被表示成數(shù)字和公式的形式后,才能被計算機計算(被計算機處理)事物到數(shù)字和公式的轉(zhuǎn)換過程叫數(shù)學建模因為:事物在計算機內(nèi)的處理都是一種計算又因為:計算就要有操作數(shù)、運算法則和計算結(jié)果所以:事物在計算機內(nèi)的處理都有操作數(shù)、運算法則和計算結(jié)果計算結(jié)果你可以留用,也可以忽略算術(shù)運算符+,-,*,/加、減、乘、除運算四則混合運算中,先算乘除,后算加減,

先算左,后算右%求余運算C語言中的運算關系運算符>,>=,<,<=,==,!=大于,大于等于,小于,小于等于,等于,不等于關系運算符運算出的結(jié)果為0和10,表示假,即該關系不成立1,表示真,即該關系成立在所有涉及到真假判斷的地方,0表示假,非0表示真找別扭inta=1;

if(a==0)

printf("OK");inta=0;

if(a==0)

printf("OK");inta=1;

if(a=0)

printf("OK");inta=0;

if(a=0)

printf("OK");==和=inta;

a=0;

a==1;inta;

a==0;

a=1;一定要分清==和=下面用法能起點小作用:inta=0;

if(0==a)

printf("OK");inta=0;

if(0=a)

printf("OK");編譯出錯邏輯運算符邏輯運算也被稱為布爾(Boolean)運算,運算結(jié)果也是1和0&&與運算(a>b&&b>c);a大于b,并且b大于c||或運算(a>b||b>c);a大于b,或者b大于c!求反(!a);如果a是0,結(jié)果非0;如果a是非0,結(jié)果是0并不改變a的值類型轉(zhuǎn)換在進行賦值操作時,會發(fā)生類型轉(zhuǎn)換將取值范圍小的類型轉(zhuǎn)為取值范圍大的類型是安全的反之是不安全的如果大類型的值在小類型能容納的范圍之內(nèi),則平安無事但是,浮點數(shù)轉(zhuǎn)為整數(shù),會丟失小數(shù)部分(非四舍五入)反之,轉(zhuǎn)換后的結(jié)果必然是錯誤的,具體結(jié)果與機器和實現(xiàn)方式有關。避免如此使用字符串與數(shù)值類型之間的轉(zhuǎn)換inti="123"這樣用是不行地atof(),atoi(),atol()把字符串轉(zhuǎn)為double,int和long定義在stdlib.h中sprintf()可以用來把各種類型的數(shù)值轉(zhuǎn)為字符串定義在stdio.h中自動類型轉(zhuǎn)換兩個同種數(shù)據(jù)類型的運算結(jié)果,還是該類型兩個不同種數(shù)據(jù)類型的運算結(jié)果,是兩種類型中取值范圍更大的那種long

double>double>float>long>int>short>char只要兩者中有一個是unsigned,就都轉(zhuǎn)為unsigned再計算把數(shù)據(jù)賦值給另外一種類型變量也會發(fā)生自動類型轉(zhuǎn)換從小到大,順利轉(zhuǎn)換從大到小,發(fā)出警告(好的編譯器會給出)類型強轉(zhuǎn)可以通過“(類型)表達式”的方式把表達式的值轉(zhuǎn)為任意類型強轉(zhuǎn)時,你必須知道你在做什么強轉(zhuǎn)與指針,并稱C語言兩大神器,用好了可以呼風喚雨,用壞了就損兵折將屠龍

刀倚天劍加一和減一運算符i++,i--,++i,--i++讓參與運算的變量加1,--讓參與運算的變量減1運算符為后綴,先取i的值,然后加/減1運算符為前綴,先加/減1,然后取i的值在一行語句中,使用加1或者減1運算的變量只能出現(xiàn)不僅可讀性差,而且因為編譯器實現(xiàn)的方法不同,容易導致不同編譯器運行效果不一樣,貽害無窮位操作運算符&按位與運算|按位或運算^按位異或運算<<按位左移運算>>按位右移運算~按位求反賦值運算符賦值運算的結(jié)果是被賦值變量賦值后的值a=b=c=0;下面兩個語句是等價的i=i+2;i+=2;+、-、*、/、%、<<、>>、&、^、|運算符都可以按此種方式處理這種形式看起來更直觀,而且執(zhí)行效率一般也能更高一些條件表達式把a和b中的最大值放入z中if(a>b)

z=a;

else

z=b;

z=(a>b)?a:b;

此種表達式切忌用得過于繁雜優(yōu)先級()[]->.!~++--+-*&(類型)sizeof*/%+-<<>><<=>>===!=&^|&&||?:=+=-=*=/=%=&=^=|=<<=>>=,優(yōu)先級能背下優(yōu)先級表的人鳳毛麟角腦細胞太寶貴了,不能用來死記硬背用括號來控制運算順序更直觀、方便,并減少出錯的概率先算乘除,后算加減,有括號就先算括號里的括號太多,有時候不清晰注意用空格做好分隔實在不行就拆分表達式C程序設計語言第3章控制流三種基本結(jié)構(gòu)順序結(jié)構(gòu)、選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu)已經(jīng)證明,任何程序均可只用這三種結(jié)構(gòu)實現(xiàn)B?hm,Corrado,andJacopiniGuiseppe.

"Flowdiagrams,Turingmachinesandlanguageswithonlytwoformationrules."

CommunicationofACM,9(5):366-371,May1966.只用這三種結(jié)構(gòu)的程序,叫結(jié)構(gòu)化程序程序“必須”符合結(jié)構(gòu)化規(guī)則流程圖順序結(jié)構(gòu)選擇結(jié)構(gòu)truefalsetruefalse循環(huán)結(jié)構(gòu)語句塊(Block){}括住的若干條語句構(gòu)成一個語句塊語句塊內(nèi)可以定義變量變量必須在語句塊的開頭定義變量僅在定義它的語句塊內(nèi)(包括下層語句塊)有效(scope.c)同一個語句塊內(nèi)的變量不可同名,不同語句塊可以同名(homonym.c)各司其職、下層優(yōu)先盡量不要在下層語句塊內(nèi)定義變量,也盡量不要定義同名變量語句塊可以用在任何可以使用語句的地方,但沒有道理要亂加語句塊if-else選擇結(jié)構(gòu)的一種最常用形式if(表達式)

語句塊1;

else

語句塊2;

語句塊3表達式值非0時,執(zhí)行語句塊1,然后語句塊3;

表達式值為0時,執(zhí)行語句塊2,然后語句塊3else部分可以沒有。當表達式值為0時,直接執(zhí)行語句3if-else嵌套使用時,注意else和誰配套的問題if.c表達式!=0?YN語句塊1語句塊2語句塊3else-ifif的一種擴展if(表達式1)

語句塊1;

elseif(表達式2)

語句塊2;

elseif(表達式3)

語句塊3;

…………

else

語句塊4;

語句塊5;else部分可以沒有表達式1!=0?YN語句塊1語句塊2語句塊5表達式2!=0?表達式3!=0?語句塊3N語句塊4NYYswitch多路選擇switch(表達式){

case

整型常數(shù)1:

語句1;

case

整型常數(shù)2:

語句2;

…………

default:

語句3;

}default可以沒有現(xiàn)場編程完成計算器……不要忘記breakswitch和else-if的比較else-if比switch的條件控制更強大一些else-if可以依照各種邏輯運算的結(jié)果進行流程控制switch只能進行==判斷,并且只能是整數(shù)判斷switch比else-if更清晰兩者都要盡量避免用得過多、過長,尤其不要嵌套得太多它們大大增加程序的分支,使邏輯關系顯得混亂,不易維護,易出錯循環(huán)——while,forwhile(表達式)

語句塊;for(表達式1;表達式2;表達式3)

語句塊;whilewhile(表達式)

語句塊1;

語句塊2;只要表達式的值為非0,就重復執(zhí)行語句塊1,直到表達式值為0時止,開始執(zhí)行語句塊2表達式!=0?YN語句塊1語句塊2forfor(表達式1;表達式2;表達式3)

語句塊;首先執(zhí)行表達式1。如果表達式2的值為非0,就重復執(zhí)行語句塊和表達式3,直到表達式2的值為0時止相當于:

表達式1;

while(表達式2){

語句塊;

表達式3;

}for的所有表達式均可省略表達式2!=0?YN語句塊表達式3表達式1注意在for和while語句之后一般沒有分號有分號表示循環(huán)體就是分號之前的內(nèi)容,即循環(huán)體不存在while(i<100);

i++;for(i=0;i<100;i++);

printf("%d",i);for通常有一個循環(huán)變量控制循環(huán)的次數(shù),不要在循環(huán)體內(nèi)改變這個變量循環(huán)——do-whiledo

語句塊1;

while(表達式);

語句塊2;首先執(zhí)行語句,然后判斷表達式的值。如果表達式為0,繼續(xù)向下執(zhí)行,否則,再次執(zhí)行語句,再次判斷表達式的值語句塊1會被執(zhí)行至少一次表達式!=0?YN語句塊1語句塊2選擇三種循環(huán)的一般思路如果循環(huán)次數(shù)已知,用for如果循環(huán)次數(shù)未知,用while如果循環(huán)體至少要執(zhí)行一次,用do-while只是思路,不是定律break和continue對for、while、do-while循環(huán)進行內(nèi)部手術(shù)break,退出循環(huán)continue,中斷此次循環(huán)的執(zhí)行,開始下一次break和continue少用為妙它們增加了循環(huán)執(zhí)行的分支,break更增加了循環(huán)的出口它們可以用來處理程序異常,而盡量不要用來處理正常流程C程序設計語言第4章函數(shù)與程序結(jié)構(gòu)函數(shù)(function)和模塊(module)函數(shù)是C語言中模塊化編程的最小單位可以把每個函數(shù)看作一個模塊若干相關的函數(shù)可以合并作一個“模塊”main()printf()scanf()power()putchar()getchar()main()stdio:printf()scanf()putchar()getchar()mymdl:power()函數(shù)的分類函數(shù)生來都是平等的,沒有高低貴賤之分,只有main()稍微特殊一點點庫函數(shù)ANSIC定義的標準庫函數(shù)符合標準的C語言編譯器必須提供這些函數(shù)函數(shù)的行為也要符合ANSIC的定義第三方庫函數(shù)由其它廠商自行開發(fā)的C語言函數(shù)庫不在標準范圍內(nèi),能擴充C語言的功能自定義函數(shù)自己編寫的函數(shù)包裝后,也可成為函數(shù)庫,供別人使用函數(shù)定義(definition)類型函數(shù)名(類型參數(shù)1,類型參數(shù)2,……)

{

函數(shù)體;

return

表達式;

}返回值類型標識符參數(shù)表返回值函數(shù)出口函數(shù)定義(definition)函數(shù)是這樣的一種運算:函數(shù)名說明運算規(guī)則參數(shù)是運算的操作數(shù)返回值是運算的結(jié)果當函數(shù)執(zhí)行到return語句或}時,函數(shù)的運算停止。程序從當次調(diào)用函數(shù)的地方繼續(xù)執(zhí)行函數(shù)可以有多個return,但最好只有一個且是最后一行用void定義返回值類型函數(shù)沒有運算結(jié)果,沒有返回值return語句之后不需要任何表達式用void定義參數(shù),表示沒有參數(shù)參數(shù)表里的參數(shù)(叫形式參數(shù),parameter)也是函數(shù)的語句塊內(nèi)的變量函數(shù)調(diào)用(call)函數(shù)名(表達式1,表達式2,……);調(diào)用一個函數(shù)之前,先要對其返回值類型、函數(shù)名和參數(shù)進行聲明(declare)不對函數(shù)進行聲明是非常危險的函數(shù)定義也有聲明函數(shù)的效果調(diào)用函數(shù)時,提供的表達式(叫實際參數(shù),argument)和該函數(shù)的形式參數(shù)必須匹配數(shù)目一致類型一一對應(會發(fā)生自動類型轉(zhuǎn)換)表達式的值賦值給對應的參數(shù)返回值可以按需處理realeql.c函數(shù)調(diào)用的過程函數(shù)的每次執(zhí)行都會建立一個全新的獨立的環(huán)境在“?!敝袨楹瘮?shù)的每個變量(包括形式參數(shù))分配內(nèi)存把實際參數(shù)的值復制給形式參數(shù)開始執(zhí)行函數(shù)內(nèi)的第一條語句函數(shù)內(nèi)的代碼在這個獨立的環(huán)境內(nèi)工作函數(shù)退出時求出返回值,將其存入一個可以被調(diào)用者訪問的地方(x86中通常使用EAX寄存器)收回分配給所有變量(包括形式參數(shù))的內(nèi)存程序控制權(quán)交給調(diào)用者,調(diào)用者拿到返回值,將其作為函數(shù)調(diào)用表達式的結(jié)果main()、printf()和scanf()

特殊嗎?main()C語言允許不對函數(shù)參數(shù)和返回值類型進行說明甚至可以連函數(shù)名都不聲明此時默認該函數(shù)的參數(shù)是不定個數(shù)的int型該函數(shù)返回值為int型永遠不要利用此特性!printf()、scanf()變長參數(shù)表,<stdarg.h>缺點:對參數(shù)類型和個數(shù)無法嚴格驗證,易使用出錯使用函數(shù)要注意每個函數(shù)只完成一個功能(包括main())對函數(shù)的功能可以用不含連詞的一句話描述函數(shù)不能過長1986年IBM在OS/360的研究結(jié)果:大多數(shù)有錯誤的函數(shù)都大于500行1991年對148,000行代碼的研究表明:小于143行的函數(shù)比更長的函數(shù)更容易維護函數(shù)一定要對傳進來的非法參數(shù)做點什么向調(diào)用者提供錯誤信息assert()safediv.c全局變量(GlobalVariable)在所有函數(shù)之外定義的變量是全局變量,在定義它的位置以后都有效全局變量自動初始化為0全局變量使函數(shù)之間的數(shù)據(jù)交換更容易,效率也高一些但是不推薦使用,甚至禁止使用程序的任何部分都可以改寫全局變量,很難確定在程序的哪里改寫了它,程序結(jié)構(gòu)混亂不得不用的時候(這種情況比較少見),要嚴格控制對它的改寫靜態(tài)變量(static)函數(shù)的內(nèi)部變量在函數(shù)退出后失效(內(nèi)存釋放)。再次進入函數(shù),變量重新定義每次函數(shù)執(zhí)行都建立一個全新的執(zhí)行環(huán)境,不受其它函數(shù)的干擾把此變量定義為static,則變量的值可以保存到下次進入函數(shù)static

inti;靜態(tài)變量自動初始化為0static.c遞歸(Recursion)函數(shù)直接或間接調(diào)用自己為遞歸unsigned

intfunc(unsigned

intn)

{

if(n==0)

return1;

else

returnn*func(n-1);

}recur.c模塊模塊包含兩部分源文件(xxx.c):一系列相關函數(shù)的定義頭文件(xxx.h):這些函數(shù)的聲明等必要信息函數(shù)聲明、外部變量聲明、宏定義、類型定義……可以將模塊編譯為.obj文件,同.h文件一起供別人使用,從而保護了源代碼使用模塊的過程建立一個工程(project)把各模塊都加入到工程中#include模塊的頭文件開始使用此模塊編寫模塊的技術(shù)模塊的信息隱藏用static定義的函數(shù)和全局變量只在此模塊內(nèi)有效(建議采用)允許被其它模塊使用的全局變量在源文件中定義,不加static修飾在頭文件中進行聲明,加extern修飾預編譯指令編譯器在開始正式編譯之前處理的指令,叫預編譯指令它們不會存在于最后生成的目標代碼中文件包含:#include用#include指定的文件內(nèi)容替換#include所在的行用<>或者""括上文件名<>表示在編譯器的include目錄內(nèi)查找文件""表示在當前目錄查找文件文件名中可以帶有路徑#define#define

宏名字

替換文本在#define之后,所有獨立出現(xiàn)“宏名字”的地方(除了字符串內(nèi))都被“替換文本”替換“替換文本”中可以有空格宏可以有參數(shù)#definemax(A,B)((A)>(B)?(A):(B))能想出帶參數(shù)的宏和函數(shù)的區(qū)別嗎?定義宏的時候注意替換發(fā)生后產(chǎn)生的非預想結(jié)果一般用括號可以避免,如上例宏名中間不要有空格與#define配套者#undef,從現(xiàn)在開始取消#define的定義#undefMAXLINE#if,#else,#elif,#endif#ifdef,#ifndef這些預編譯指令通常用來處理多文件工程和程序多版本的問題。(程序多版本一般是不同平臺的版本,不同用戶等級的版本,不同開發(fā)階段的版本等)使用預編譯指令的目的增強程序可讀性但是調(diào)錯時宏可能帶來很多難題精簡源代碼,提取變化這一點更多時候用函數(shù)的效果更好,但宏也有其不可替代的優(yōu)勢不編譯無用代碼,精煉目標代碼C程序設計語言第5章指針與數(shù)組計算機內(nèi)的存儲部件,活動中的所有指令和數(shù)據(jù)都保存在內(nèi)存內(nèi)速度快,但是掉電即失可以隨機訪問只要指名要訪問的內(nèi)存單元的地址,就可以立即訪問到該單元地址是一個無符號整數(shù)(通常用16進制數(shù)),其字長與主機相同內(nèi)存中的每個字節(jié)都有唯一的一個地址內(nèi)存(RandomAccessMemory)

地址(Address)指針的故事“該程序執(zhí)行了非法操作,即將關閉”這種錯誤幾乎全是由指針和數(shù)組導致的黑客攻擊服務器利用的bug絕大部分都是指針和數(shù)組造成的有些非計算機專業(yè)的人,盡量避免使用指針指針的故事鐵桿C/C++程序員最摯愛的武器:指針指針造就了C/C++的高效和強大很多不可能的任務由指針完成main(){char*a="main(){char*a=%c%s%c;printf(a,34,a,34);}";printf(a,34,a,34);}關于指針的原則學習原則一定要學會其實通常的應用很簡單就是一個變量復雜的應用也不建議使用使用原則永遠要清楚每個指針指向了哪里永遠要清楚指針指向的位置是什么數(shù)組(Array)若干類型相同的相關數(shù)據(jù)湊到一起,就是數(shù)組定義類型數(shù)組名[整型常數(shù)1][整型常數(shù)2]……[整型常數(shù)n];inta[6][4];使用a[0][0]、a[1][2]、a[5][3]每個元素都是一個普通變量下標可以是任意整型表達式數(shù)組的各個元素在內(nèi)存中分布在一起,分布規(guī)律是……array.c思考一下一維和三維數(shù)組怎么分布呢?從類型的角度理解數(shù)組inta[10];定義了一個有10個int類型元素的數(shù)組a的類型可以看作int[10](只是看作,語法并不允許這么定義:int[10]a)inta[20][10];定義了一個有20個int[10]類型元素數(shù)組a[0]、a[1]……a[9]的類型是int[10],所以a[0][0]、a[0][1]……a[19][9]的類型是intinta[30][20][10];這個呢?這種特性決定了數(shù)組元素在內(nèi)存的分布規(guī)律,也解釋了數(shù)組的很多語法現(xiàn)象數(shù)組初始化數(shù)組定義后的初值仍然是隨機數(shù),一般需要我們來初始化inta[5]={12,34,56,78,9};inta[5]={0};inta[]={11,22,33,44,55};數(shù)組大小最好用宏來定義,以適應未來可能的變化#defineSIZE10

inta[SIZE];數(shù)組的使用數(shù)組的下標都是從0開始對數(shù)組每個元素的使用與普通變量無異可以用任意表達式作為下標,動態(tài)決定訪問哪個元素for(i=0;i<SIZE;i++)

a[i]=2*i;下標越界是大忌!使用大于最大下標的下標,將訪問數(shù)組以外的空間。那里的數(shù)據(jù)不是我們所想定的情況,可能帶來嚴重后果有時,故意越界訪問數(shù)組會起到特別效果,但一定要對自己在做什么了如指掌sizeof可以用來獲得數(shù)組所占字節(jié)數(shù)sizeof(a)sizeof(a[0])數(shù)組的用處與特點保存大量同類型的相關數(shù)據(jù)快速地隨機訪問一旦定義,不能再改變大小在編譯階段就確定了數(shù)組的大小數(shù)組名幾乎就是一個指針指針(Pointer)int*p;定義了一個指針變量p,簡稱指針pp是變量,int*是類型變量都占用內(nèi)存空間,p的大小是sizeof(int*)p用來保存地址。此時這個地址是哪呢(p指向哪呢)?inti;

p=&i;*p就像普通的變量一樣使用,其值是p指向的內(nèi)存的內(nèi)容,類型是int(在上例和i等價)p可以動態(tài)(任意)地指向不同內(nèi)存,從而使*p代表不同的變量p=0;p=&a[0];指針指針也是數(shù)據(jù)類型。指向不同數(shù)據(jù)類型的指針,分別為不同的數(shù)據(jù)類型int*、float*、char*、int**、int***……指針指向非其定義時聲明的數(shù)據(jù)類型,將引起warningvoid*類型的指針可以指向任意類型的變量指針在初始化時一般int*p=NULL;NULL表示空指針,即無效指針但它只是邏輯上無效,并不是真正地無效如果指針指向一個非你控制的內(nèi)存空間,并對該空間進行訪問,將可能造成危險&與*運算符&運算的結(jié)果指向該變量的指針inti,*p;

p=&i;int*p,a[10];

p=a;int*p,a[10];

p=&a[0];int*p,a[10];

p=&a[5];*和指針的組合是一個變量,該變量的地址和類型分別是指針指向的地址和指針定義時指向的類型inti,*p;

p=&i;

*p=0;int*p,a[10];

p=a;

*p=0;int*p,a[10];

p=&a[0];

*p=0;int*p,a[10];

p=&a[5];

*p=0;指針與數(shù)組數(shù)組名可以看作一個指針只是不能修改這個指針的指向常指針inta[10];a的類型是int[10]a的類型也是int*指針可當作數(shù)組名使用,

反之亦然int*p,a[10];

p=a;

p[1]=0;

*a=0;指針運算int*p=NULL;

p++;

/*p的值會是多少?*/指針的加減運算是以其指向的類型的字長為單位的int*p,a[10];

p=a;*(p+3)等價于a[3]p++;

*p等價于a[1]指針運算int*p,*q,a[10];

p=a;

q=&a[2];q-p==?q=p+3;運算法則只能進行加減和關系運算只能同類型指針之間或指針與整數(shù)之間運算“類型”本不存在存儲器在保存數(shù)據(jù)時并不關心數(shù)據(jù)的類型完全以二進制方式工作我們向計算機發(fā)出的指令說明了某塊內(nèi)存里數(shù)據(jù)的類型一塊內(nèi)存內(nèi)保存著(61626364)16以char類型看待每個字節(jié):"abcd"以float類型看待每個字節(jié):16777999408082104000000.000000以int類型看待每個字節(jié):1684234849依天屠龍,強強聯(lián)手intmain(void)

{

inta[]={0,1,2,3,4,5,6,7,8};

inti;

unsigned

char*p;

p=(unsigned

char*)a;/*類型強轉(zhuǎn)了*/

for(i=0;i<sizeof(a);i++)

{

PrintHexChar(p[i]);/*把指針當數(shù)組用*/

putchar('');

}

}指針強轉(zhuǎn)后,可以把一塊內(nèi)存當作另一種類型來處理強強聯(lián)手,我們可以隨意控制任意內(nèi)存god.c指針與函數(shù)指針既然是數(shù)據(jù)類型,自然可以做函數(shù)的參數(shù)和返回值的類型指針做參數(shù)的經(jīng)典例子:main()

{

intx,y;

swap(x,y);

}voidswap(intx,inty)

{

inttemp;

temp=x;

x=y;

y=temp;

}NotWork指針做參數(shù)main()

{

intx,y;

swap(&x,&y);

}voidswap(int*px,int*py)

{

inttemp;

temp=*px;

*px=*py;

*py=temp;

}這里的函數(shù)調(diào)用過程還是“實參”的內(nèi)容復制到“形參”,千萬不要理解成什么

“傳引用調(diào)用”指針做返回值printf("%s",GetInput());

......

char*GetInput(void)

{

charstr[100];

scanf("%s",str);

returnstr;

}charstring[30];

printf("%s",GetInput(string));

......

char*GetInput(char*str)

{

scanf("%s",str);

returnstr;

}√三個月使用scanf目睹之怪現(xiàn)狀inti;

scanf("%d",i);

/*這樣會如何?*/inti;

scanf("%f",&i);

/*這樣又會如何?*/charc;

scanf("%d",&c);

/*這樣呢?*/i的值被當作地址。例如,i的值如果是100,那么輸入的整數(shù)就會從地址100開始寫入內(nèi)存輸入被當作float,以float的二進制形式寫到i所在的內(nèi)存空間輸入以int的二進制形式寫到c所在的內(nèi)存空間。c所占內(nèi)存不足以放下一個int,其后的空間也被覆蓋數(shù)組做參數(shù)和指針一回事兒……voidProcessArray(int*a)

{

......

}voidProcessArray(inta[])

{

......

}這里給定元素個數(shù)有意義嗎?動態(tài)分配內(nèi)存在<stdlib.h>和<alloc.h>中均定義了下面的函數(shù)void*malloc(size_tsize);size_t是在<stddef.h>中定義的數(shù)據(jù)類型,就是一個unsigned

int向系統(tǒng)申請大小為size的內(nèi)存塊,把指向首地址的指針返回。如果申請不成功,返回NULLvoidfree(void*block);釋放由malloc()申請的內(nèi)存塊。block是指向此塊的指針malloc申請的內(nèi)存,在被free之前,程序的任何部分都可以使用當然,要使用必須得到指向它的指針動態(tài)分配內(nèi)存如果malloc()申請的內(nèi)存不被free()程序就退出,將產(chǎn)生內(nèi)存泄露(Memory

Leak)“內(nèi)存泄露”一詞類似“原料泄露”。泄露出去的原料不能被利用,導致生產(chǎn)過程中原料不足malloc()時,系統(tǒng)找到一塊未占用的內(nèi)存,將其標記為已占用,然后把地址返回,表明此程序占用此塊內(nèi)存,其它程序不能再用它free()時,系統(tǒng)標記此塊內(nèi)存為未占用,本程序不能繼續(xù)使用,所有程序可以申請使用如果malloc()之后不free(),此塊內(nèi)存將永遠不會被任何程序使用,就好像這塊內(nèi)存泄露出去一樣防止內(nèi)存泄露之道在需要的時候才malloc,并盡量減少malloc的次數(shù)能用自動變量解決的問題,就不要用malloc來解決malloc一般在大塊內(nèi)存分配和動態(tài)內(nèi)存分配時使用malloc本身的執(zhí)行效率就不高,所以過多的malloc會使程序性能下降可以重復利用malloc申請到的內(nèi)存盡量讓malloc和與之配套的free在一個函數(shù)內(nèi)盡量把malloc集中在函數(shù)的入口處,free集中在函數(shù)的出口處以上做法只能盡量降低產(chǎn)生泄露的概率。完全杜絕內(nèi)存泄露,關鍵要靠程序員的細心與責任感字符串(String)

與字符數(shù)組、字符指針字符串一串以'\0'結(jié)尾的字符在C語言中被看作字符串用雙引號括起的一串字符是字符串常量,C語言自動為其添加‘\0’終結(jié)符"Helloworld!"把字符串常量作為表達式直接使用,得到的值是該常量的地址C語言并沒有為字符串提供任何專門的表示法,完全使用字符數(shù)組和字符指針來處理字符數(shù)組每個元素都是字符類型的數(shù)組charstring[100];字符指針指向字符類型的指針char*p;數(shù)組和指針可以等同看待,上面三者本質(zhì)上是一回事字符串處理函數(shù)在<string.h>中定義了若干專門的字符串處理函數(shù)strcpy:string

copy

char*strcpy(char*dest,const

char*src);strlen:string

lengthsize_tstrlen(const

char*s);strcat:string

combinationchar*strcat(char

*dest,constchar

*src);strcmp:string

comparisonintstrcmp(const

char*s1,const

char*s2);stricmp:string

comparison

ignoring

caseintstricmp(const

char*s1,const

char*s2);指針、數(shù)組以及其它的類型混合基本數(shù)據(jù)類型int、long、char、short、float、double……指針是一種數(shù)據(jù)類型是從其它類型派生的類型XX類型的指針數(shù)組也是一種數(shù)據(jù)類型是從其它類型派生的類型每個元

溫馨提示

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

評論

0/150

提交評論