C語言(第四章)(下).ppt_第1頁
C語言(第四章)(下).ppt_第2頁
C語言(第四章)(下).ppt_第3頁
C語言(第四章)(下).ppt_第4頁
C語言(第四章)(下).ppt_第5頁
已閱讀5頁,還剩43頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第四章 模塊化程序設計 (函數(shù)),五、變量的存儲屬性,模塊化設計要求研究不同模塊(函數(shù)、源文件)間變量的關系。 變量兩大屬性: 數(shù)據(jù)類型 存儲屬性,1、數(shù)據(jù)類型(復習) 通過變量說明(定義)來規(guī)定其數(shù)據(jù)類型: 格式 數(shù)據(jù)類型關鍵字 變量名 如 char a; int b,c ; float x,y; 為什么使用變量前要先對其數(shù)據(jù)類型進行“說明”好比看電影前先買票訂座 預留存儲空間(如char型為1個字節(jié),int型為2個字節(jié)) 確定存儲方式(如char型存放ASCII值,int型存放補碼值),復習,數(shù)據(jù)存儲形式 字符型按ASCII碼存儲,其余以補碼存儲,一個變量的數(shù)據(jù)類型定義后,就規(guī)定了該變量只能存儲相應類型的數(shù)據(jù)。如定義int x,則x只能存放整型數(shù),如果x=3.14159,會被自動轉(zhuǎn)為整型存放。,變量兩大屬性: 數(shù)據(jù)類型 存儲屬性 以下這些都稱為變量的存儲屬性,變量的可用域:一個變量在程序的哪個范圍內(nèi)是可以使用的; 變量的生存期:它什么時候生成以及什么時候被撤消; 變量的存儲類型:它存儲在哪種類型的存儲器中以及用什么機制進行存儲。,(一)、局部變量與全局變量 P127,1、局部變量函數(shù)內(nèi)部或復合語句內(nèi)定義的變量,變量的可用域是指一個變量的標識符在程序的哪個域內(nèi)才是可以被識別的,也稱為可見(或可用)的。大體上可以分為兩種:全局可用全局變量與局部可用局部變量。,所有形參都是局部變量; 局部變量只在本函數(shù)或本復合語句內(nèi)才能使用,在此之外不能使用(視為不存在)main函數(shù)也不例外。,2、全局變量在函數(shù)之外定義的變量,有效作用范圍:從定義變量位置開始直到本源文件結束 如果需要將全局變量的作用范圍擴展至整個源文件 法1 全部在源文件開頭處定義 法2 在引用函數(shù)內(nèi),用extern說明 法3 在源文件開頭處,用extern說明,【例】求程序運行結果 extern int x,y; main( ) clrscr(); printf(“x=%d,y=%dn“,x,y); int x=100,y=200;,結果:x=100,y=200,去掉第一行試試,如果要將全局變量作用范圍擴展到其他源文件,只需在使用這些變量的文件中對變量用extern加以說明。,int a=3,b=5; max(int a,int b) int c; c=ab?a:b; return c; main() int a=8; printf(“%dn“,max(a,b); ,【例】求程序運行結果,如果主函數(shù)中沒有int a=8,結果?,【結果】 5,如果讓主函數(shù)中int a=4或a=-1,結果?,【結果】 均為 5,【結果】 8,void num() extern int x,y; int a=15,b=10; x=a-b; y=a+b; int x,y; main() int a=7,b=5; x=a+b; y=a-b; num(); printf(“%d,%dn“,x,y); ,【例】求程序運行結果,如果第二行不加上extern呢?,【結果】 5,25,【結果】 12,2,int a; fun(int i) a+=2*i; return a; main() int a=10; clrscr( ); printf(“%d,%dn“,fun(a),a); ,【例】求程序運行結果,【結果】 20,10,(二) 動態(tài)變量與靜態(tài)變量,程序,內(nèi)存中都被分成代碼區(qū)和數(shù)據(jù)區(qū)兩大部分。 而數(shù)據(jù)區(qū)又被分為靜態(tài)存儲區(qū)、自動存儲區(qū)和動態(tài)分配區(qū)等三部分。 分配在靜態(tài)存儲區(qū)的變量在程序開始執(zhí)行時被創(chuàng)建并自動初始化(數(shù)值變量被初始化為0),當程序結束時才被撤銷。所以常稱靜態(tài)變量的生存期是永久的。 全局變量就是被分配在靜態(tài)存儲區(qū)的。,main() int a=2,i; clrscr( ); for (i=0;i3;i+) printf(“%4d“,f(a); f(int a) int b=0; static int c=3; b+;c+; return a+b+c; ,【例】求程序運行結果,變量跟蹤 main( ) f函數(shù) a i b c f(a) 2 0 01 4 7 1 01 5 8 2 01 6 9 【結果】 7 8 9,如果去掉static呢?,【結果】 7 7 7,main() int k=4,m=1,p; clrscr(); p=func(k,m); printf(“%d,“,p); p=func(k,m); printf(“%d“,p); func(int a,int b) static int m=0,i=2; i+=m+1; m=i+a+b; return m; ,【例】求程序運行結果,變量跟蹤 main( ) func函數(shù) k m a b m i 4 1 4 1 08 23 4 1 4 1 817 312 【結果】 8, 17,如果去掉static呢?,【結果】 8, 8,#include main() int a=3, b=2, c=1; int b=5, c=12; c-=b*2; printf(“a=%d,b=%d,c=%dn“, a, b, c); a+=c; printf(“a=%d,b=%d,c=%dn“, a, b, c); ,【例】求程序運行結果,【結果】 a=3,b=5,c=2 a=5,b=2,c=1,(三) C語言中變量的存儲類型 P132,規(guī)定了變量在計算機內(nèi)部的存放位置決定變量的“壽命”(何時“生”,何時“滅”) 一個完整的變量說明格式如下: 存儲類別 數(shù)據(jù)類型 變量名 如 static int x , y ; C程序的存儲類別有: register型(寄存器型)局部自動類型 auto型(自動變量型)局部自動類型 static型(靜態(tài)變量型)靜態(tài)局部類型或靜態(tài)全局類型 extern型(外部變量型)全局類型,C程序的變量存儲位置,變量的生存期 靜態(tài)存儲區(qū)中的變量:與程序“共存亡” 動態(tài)存儲區(qū)中的變量:與函數(shù)“共存亡” 寄存器中的變量:同動態(tài)存儲區(qū),C程序的變量存儲類別,變量的生存期 靜態(tài)存儲區(qū)中的變量 與程序“共存亡” 動態(tài)存儲區(qū)中的變量 與函數(shù)“共存亡” 寄存器中的變量 同動態(tài)存儲區(qū), register型(寄存器型) 變量值存放在運算器的寄存器中存取速度快,一般只允許23個,且限于char型和int型,通常用于循環(huán)變量(在微機的Turbo C中實際上自動轉(zhuǎn)為auto型)。 auto型(自動變量型) auto 數(shù)據(jù)類型變量名=初值表達式,; 變量值存放在主存儲器的動態(tài)存儲區(qū)(堆棧方式); 優(yōu)點同一內(nèi)存區(qū)可被不同變量反復使用。 以上兩種變量均屬于“動態(tài)存儲型”,即調(diào)用函數(shù)時才為這些變量分配單元,函數(shù)調(diào)用結束其值自動消失。,C程序的變量存儲類別,變量的生存期 靜態(tài)存儲區(qū)中的變量 與程序“共存亡” 動態(tài)存儲區(qū)中的變量 與函數(shù)“共存亡” 寄存器中的變量 同動態(tài)存儲區(qū), static型(靜態(tài)變量型) 變量值存放在主存儲器的靜態(tài)存儲區(qū) 程序執(zhí)行開始至結束,始終占用該存儲空間 extern型(外部變量型) 同上,其值可供其他源文件使用 以上兩種均屬于“靜態(tài)存儲”性質(zhì),即從變量定義處開始,在整個程序執(zhí)行期間其值都存在(都可用!),未說明存儲類別時, 函數(shù)內(nèi)定義的變量默認為auto型 函數(shù)外定義的變量默認為extern型。,用const聲明將變量存儲在只讀區(qū),C語言除了可以為程序開辟棧區(qū)、堆區(qū)、靜態(tài)區(qū)外,還可以開辟一個只讀區(qū)。既然只讀區(qū)是內(nèi)存的一個區(qū),所以數(shù)據(jù)是以變量的形式存儲的,但它又是只讀的,即不可修改的。所以這也就是把變量定義為只讀變量。定義只讀變量的方法是在聲明變量時使用修飾符const。格式為:,const 數(shù)據(jù)類型 變量1=初始表達式1,變量2=初始表達式2,,舉 例 說 明,通過下面例子說明這3種類型的變量的變化情況:,main( ) auto int a=2; register int b=2; static int c=2; printf(“-a=%d,b=%d,c=%d -n“,a,b,c); f(a); /*調(diào)用f*/ f(b); /*調(diào)用f*/ f(c); /*調(diào)用f*/ printf(“-a=%d,b=%d,c=%d -n“,a,b,c); ,main的局部變量,2,2,2,動態(tài)存儲區(qū),靜態(tài)存儲區(qū),第一次調(diào)用f函數(shù),實參為a=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部變量,2,2,2,10,0,20,12,18,4,第二次調(diào)用f函數(shù),實參為b=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部變量,2,2,2,10,4,20,12,18,8,第三次調(diào)用f函數(shù),實參為c=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部變量,2,2,2,10,8,20,12,18,12,C語言程序的加工過程,六、模塊的編譯和鏈接,1 分別編譯 C語言是一種支持模塊化程序設計的語言,它允許將一個大型程序分成多個程序文件分別進行編譯。這樣的好處在于 當程序的一個局部有錯誤或?qū)植窟M行了修改時,可以只重新編譯該局部,不需要將整個程序都重新編譯。 某些經(jīng)過考驗的函數(shù)的目標代碼可以添加為的庫函數(shù),供其他程序中使用。,2 用項目管理多文件程序的編譯與鏈接過程,多文件程序的編譯、鏈接過程是比較麻煩的。為了方便用戶進行多文件程序的編譯、鏈接,各種程序開發(fā)軟件都提供了用項目(project)管理多文件程序的編譯和鏈接過程。其使用方法因開發(fā)工具而異,請參考有關手冊。,3 頭文件,用戶顯式地保證程序一致性的基本方法是保持聲明的一致性。保持聲明一致性的簡單辦法是提供一個頭文件,讓頭文件中的信息作為各模塊之間的接口信息,有利于提供可重用的模塊。使用頭文件將把程序分為程序頭和程序體兩部分。 好的頭文件應包含如下一些內(nèi)容: 類型定義,如定義一個枚舉類型enum color RED,BLUE,GREEN,YELLOW; 函數(shù)聲明,如extern int strlen const char*; 嵌入函數(shù)聲明,如inline char get() return *p+; 數(shù)據(jù)聲明,如extern int a; 常量定義,如const float pi=3.141593; 包含指令,如#include ,3 頭文件,宏定義,如#define case break; case 注釋 好的頭文件不能包含以下內(nèi)容: 一般函數(shù)定義 數(shù)據(jù)定義,如int a; 常量聚集定義,如 const tbl=/* */; 用戶頭文件是由用戶自己定義的頭文件。系統(tǒng)將用雙引號方式進行搜索。程序員可以用它們建立各文件之間的信息窗口。 應當注意,修改了頭文件時,所有涉及該頭文件的程序都應重新編譯,所以在編制頭文件時應盡量考慮周全;另外,當使用很多頭文件時,常常有重復嵌入的情形發(fā)生,在這種情形下,應防止標識符重復定義的錯誤。為避免這些錯誤,應使用條件編譯來測試有無重復定義。,七、編譯預處理,編譯預處理: P139 宏定義 文件包含 條件編譯 【編譯】C編譯系統(tǒng)對源程序進行:詞法和語法分析,代碼生成,優(yōu)化 .OBJ文件 【編譯預處理】編譯前對源程序進行一些預加工(改善程序設計環(huán)境/模塊化設計) 編譯預處理命令均以#開頭,未尾不加分號 可出現(xiàn)在程序的任何位置,其作用范圍:出現(xiàn)點至所在源程序未尾。,七、編譯預處理,以“#”開頭的一些命令,它通知編譯系統(tǒng):在進行正式編譯前應當先進行一些前期工作(即編譯預處理)。,目前,C語言的編譯預處理功能主要有如下一些: 1)文件包含,使用命令:#include。 2)宏定義,使用命令:#define、#undef。 3)條件編譯,使用命令:#if、#ifdef、#ifndef、#else、#endif 4)提供行號信息,使用命令:#line。 5)編譯雜注,使用命令:#progma。 6)錯誤信息,使用命令:#error。,編譯預處理中,應用最多的是對宏的處理。它允許程序員使用define定義并應用宏名字書寫C語言程序,同時也指示編譯器在正式編譯前通過宏替換,使程序能按照C語言的語法進行編譯。,1 字符串宏定義及其基本格式,define命令最簡單的應用是將一個字符串定義為一個宏名,格式為: define 宏名 字符串 這個過程稱為宏替換。符號常數(shù)的定義就是這種宏定義的一種應用。例如 #define PI 3.14159265 #define RADIUS 2.0 使用宏定義的好處是: (1) 提高了程序的可讀性。如果人們看到以下語句 return (2.0* 3.1415926536* 2.0); 和 return (3.1415926536* 2.0* 2.0); 以及: return (2.0* PI* RADIUS); 和 return (PI *RADIUS* RADIUS); 使用宏定義可以提高可理解性。 (2) 易修改性好。,定義符號常量,【例】 #define M 3 #define N (M+1) #define NN N*N/2 main() clrscr(); printf(“NN=%d,“,NN); printf(“5*NN=%dn“,5*NN); ,結果:NN=8,5*NN=40,【討論】 如果第二行改為: #define N M+1,結果: NN=6,5*NN=18,2 使用宏需要注意的問題,定義符號常量,【例】 #define OK 1 main() printf(“OK=%dn“,OK); ,結果:OK=1,【討論】 程序中用雙括號括起來的字符串中的字符即使與宏名相同,也不進行替換。,3 撤銷已定義的宏,用命令undef可以撤銷已定義的宏。如: #define OK 1 #undef OK 在#undef命令行之后的范圍,OK不再代表1。,4、帶參數(shù)的宏定義 格式 #define 宏名(參數(shù)表) 宏體,【例】 #define PI 3.14159 #define s(r) PI*r*r main() float a=1,sum; sum=s(a); printf(“r=%.0f,s=%fn“,a,sum); ,結果: r=1,s=3.141590,帶參數(shù)的宏定義,【例】 #define PT 5.5 #define s(A) PT*A*A main() int a=1,b=2; printf(“%4.1fn“,s(a+b); ,結果:9.5,【討論】注意s(a+b)不是函數(shù),它不做任何計算(如果是函數(shù),則s(a+b)為s(3),結果49.5),s(a+b)=5.51212=9.5,帶參數(shù)的宏定義,【例】選擇正確答案 #include “stdio.h“ #define SUM(y) 1+y main( ) int x=2; printf(“%dn“,SUM(5)*x); A) 10 B) 11 C) 12 D) 15,結果:B,對于求平方的宏定義,可以寫出4種形式: #define SQUARE(x) x*x /* (a) */ #define SQUARE(x)(x*x) /* (b) */ #define SQUARE(x) (x)*(x) /* (c) */ #define SQUARE(x) (x)*(x) /* (d) */ 到底哪個對呢?下面用幾個表達式進行測試:,用表達式a=SQUARE(n+1)測試, 按(a),將替換為a=n+1*n+1。顯然結果不對。 按(b),將替換為a=(n+1*n+1),結果與按(a)相同。 按(c),將替換為a=(n+1)*(n+1),結果對。 按(d),將替換為a=(n+1)*(n+1),結果對。,用表達式a=16/SQUARE(2)測試 對剩下的(c)和(d)進行測試。 按 (c) ,將替換為a=16/(2)*(2)=32,顯然結果不對。 按 (d) ,將替換為a=16/((2)*(2))=4,結果對。,2、文件包含,#include 標準方式 只按標準方式(系統(tǒng)存放C庫函數(shù)頭文件所在目錄)查找所要包含的文件 對TC,默認只在tcinclude目錄下查找 #include “ “ 先在源文件所在目錄找指定頭文件,若無再按標準方式找(更保險),文件包含命令的處理過程,首先尋找所要求包含的文件,如果找到,就用這個文件的全部內(nèi)容取代當前文件里的這個包含命令行。被替換進來的文件里仍然可以有文件包含等預處理命令行,這些預處理也會被處理。,文件包含示意圖,#include #include 源程序area.c (用戶編寫),頭文件stdio.h (系統(tǒng)提供),頭文件math.h (系統(tǒng)提供),area.exe (可執(zhí)行程序),stdio.h math.h area.c,編譯/ 連接,第一章例一中,area.c文件本身只有12行,stdio.h有187行, math.h有107行, 實際上stdio.h本身還包括 一個24行的頭文件stdarg.h。 “文件包含”是在編譯后連接時“包含”進可執(zhí)行程序的。 比較:area.c 1kb; area.obj 1kb; area.exe 26kb,stdarg.h,stdio.h stdarg.h math.h area.c,3、條件編譯,根據(jù)條件決定是否編譯某一組語句。常用形式:, 如果標識符被定義過* 如果標識符未被定義過 #ifdef 標識符 #ifndef 標識符 程序段1 程序段1 /*編譯此程序段*/ #else #else /*#else部分可省略*/ 程序段2 程序段2 /*反之,編譯此程序段*/ #endif #endif *此處指標識符用#define等命令定義過。,3、條件編譯, #if 表達式 /*如果表達式為真*/ 程序段1 /*編譯程序段1*/ #else 程序段2 /否則*編譯程序段2*/ #

溫馨提示

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

評論

0/150

提交評論