第二章 C語言編程實(shí)踐.ppt_第1頁
第二章 C語言編程實(shí)踐.ppt_第2頁
第二章 C語言編程實(shí)踐.ppt_第3頁
第二章 C語言編程實(shí)踐.ppt_第4頁
第二章 C語言編程實(shí)踐.ppt_第5頁
已閱讀5頁,還剩88頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、上章回顧,宏定義特點(diǎn)和注意細(xì)節(jié) 條件編譯特點(diǎn)和主要用處 文件包含的路徑查詢規(guī)則 C語言擴(kuò)展宏定義的用法,C語言編程實(shí)踐,第二章,預(yù)習(xí)檢查,異或的運(yùn)算符是什么 宏定義最主要的特點(diǎn)是什么 請(qǐng)列舉條件編譯三大用法 在文件包含中 和“” 有什么區(qū)別 如何取得整數(shù)register中的第五位值,本章結(jié)構(gòu),指針特性,C語言編程實(shí)踐,C語言常犯錯(cuò)誤,C語言關(guān)鍵詞,C語言編程調(diào)試,C語言編程要點(diǎn),位段,位運(yùn)算,課程目標(biāo),了解位運(yùn)算的實(shí)際應(yīng)用。 了解C語言幾個(gè)重要關(guān)鍵詞的特性和他們之間區(qū)別 熟悉C語言編程要點(diǎn) 熟悉C語言常見的語法錯(cuò)誤以及解決方法 了解如何去定位錯(cuò)誤以及解決錯(cuò)誤,2 C語言編程實(shí)踐,位運(yùn)算 指針特

2、性 C語言關(guān)鍵詞 C語言幾個(gè)以混淆的概念 C語言編程易犯毛病集合,2.1 位運(yùn)算,按位與運(yùn)算 按位或運(yùn)算 按位異或運(yùn)算 求反運(yùn)算 左移運(yùn)算 右移運(yùn)算,2.1 位運(yùn)算,位運(yùn)算符的含義 位運(yùn)算是指進(jìn)行二進(jìn)制位的運(yùn)算。 功能: c語言提供對(duì)內(nèi)存單元的二進(jìn)制位的操作,使得c語言能夠編寫系統(tǒng)軟件. 位運(yùn)算符 運(yùn)算對(duì)象只能為整型或字符型數(shù)據(jù). 各個(gè)位運(yùn)算符號(hào)的使用:,2.1.1按位與運(yùn)算,按位與 printf(Input a integer number: ); scanf(%d, ,程序運(yùn)行情況: Input a integer number:1000 result=0 x3 程序說明: ( 0 p =

3、 p-sizeof(int)。,2.3.2 函數(shù)指針,數(shù)據(jù)指針的三個(gè)問題 C語言中函數(shù)名直接對(duì)應(yīng)于函數(shù)生成的指令代碼在內(nèi)存中的地址,因此函數(shù)名可以直接賦給指向函數(shù)的指針; 調(diào)用函數(shù)實(shí)際上等同于“調(diào)轉(zhuǎn)指令參數(shù)傳遞處理回歸位置入棧”,本質(zhì)上最核心的操作是將函數(shù)生成的目標(biāo)代碼的首地址賦給CPU的PC寄存器; 因?yàn)楹瘮?shù)調(diào)用的本質(zhì)是跳轉(zhuǎn)到某一個(gè)地址單元的code去執(zhí)行,所以可以調(diào)用一個(gè)根本就不存在的函數(shù)實(shí)體。,2.3.2 函數(shù)指針,數(shù)據(jù)指針實(shí)例 /* 定義一個(gè)無參數(shù)、無返回類型的 */ typedef void (*lpFunction) ( ); /* 函數(shù)指針類型 */ /*定義一個(gè)函數(shù)指針,指向*

4、/ lpFunction lpReset = (lpFunction)0 xF000FFF0; /* CPU啟動(dòng)后所執(zhí)行第一條指令的位置 */ lpReset(); /* 調(diào)用函數(shù) */,2.3.3 數(shù)組與動(dòng)態(tài)申請(qǐng),動(dòng)態(tài)申請(qǐng)內(nèi)存方式可以用較大的數(shù)組替換 盡可能的選用數(shù)組,數(shù)組不能越界訪問; 如果使用動(dòng)態(tài)申請(qǐng),則申請(qǐng)后一定要判斷是否申請(qǐng)成功了,并且malloc和free應(yīng)成對(duì)出現(xiàn)!,2.4 C語言關(guān)鍵詞,const typedef 與define define 與 enum static,2.4.1 const,const -只讀 說說以下的區(qū)別 const int a; int const a

5、; const int *a; int * const a; int const * a const; const的優(yōu)勢(shì) 關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息 防止便利被無意的代碼修改,2.4.1 const,const -只讀 說說以下的區(qū)別 const int a; int const a; const int *a; int * const a; int const * a const; Const的優(yōu)勢(shì) 關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息 通過給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼 防止便利被無意的代碼修改,2.

6、4.2 typedef 與define,#define 預(yù)處理指令 在編譯預(yù)處理時(shí)進(jìn)行簡(jiǎn)單的替換, 不作正確性檢查 不需要再在內(nèi)存中分配變量空間 調(diào)試程序無法檢查用#define說明的常量 用#under指令取消 typedef 聲明一個(gè)新的類型名代替已有的類型名 在編譯時(shí)處理的 不實(shí)際分配內(nèi)存空間,2.4.2 typedef 與define,#define實(shí)例 #define your_int int * your_int a, b; 結(jié)果 相當(dāng)于int *a, b; 只是簡(jiǎn)單的宏替換 即 int *a; int b;,typedef例子 typedef int * your_int; yo

7、ur_int a, b 結(jié)果 /a, b 都為指向int的指針 即 int *a; int *b;,2.4.3 define 與 enum,#enum 特點(diǎn) 用enum關(guān)鍵字說明的常量由編譯程序自動(dòng)生成,程序員不需要用手工對(duì)常量一一賦值。 用enum關(guān)鍵字說明常量使程序更清晰易讀,因?yàn)樵诙xenum常量的同時(shí)也定義了一個(gè)枚舉類型標(biāo)識(shí)符。 在調(diào)試程序時(shí)通??梢詸z查枚舉常量。 需要分配內(nèi)存來存儲(chǔ)常量,2.4.3 define 與 enum,#enum 例子 enum Error_Code OUT_OF_MEMORY, INSUFFICIENT_DISK_SPACE, LOGIC_ERROR, FI

8、LE_NOT_FOUND ;,2.4.3 define 與 enum,#enum 相對(duì)#define的優(yōu)勢(shì) 使程序更容易維護(hù) 使程序更易讀 使程序調(diào)試起來更方便,2.4.4 static,static的特點(diǎn) 本地的全局變量 限制變量的作用域 設(shè)置變量的存儲(chǔ)域 static 的作用 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,2.5 C語言編程要點(diǎn),C語言存儲(chǔ)空間布局 Heap與stack static特

9、性應(yīng)用 字符串常量 array_name和 extern int n; int main() n = 20; printf(%dn,n); display(); return 0; ,static int n; /*定義全局靜態(tài)變量,自動(dòng)初始化為0,僅在本文件中可見*/ void display() n+; printf(%dn,n); ,結(jié)果: 文件分別編譯通過,但link的時(shí)候teststatic1.c中的變量n找不到定義,2.5.3.1全局靜態(tài)變量,優(yōu)勢(shì) 不會(huì)被其他文件所訪問,修改 其他文件中可以使用相同名字的變量,不會(huì)發(fā)生沖突。 靜態(tài)局部變量和普通局部變量的區(qū)別 static局部變量只

10、被初始化一次,下一次依據(jù)上一次結(jié)果值; static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個(gè)被調(diào)用中維持一份拷貝,2.5.3.2 局部靜態(tài)變量,定義 局部變量之前加上關(guān)鍵字static 。 特征 內(nèi)存中的位置:靜態(tài)存儲(chǔ)區(qū) 初始化:未經(jīng)初始化的全局靜態(tài)變量會(huì)被程序自動(dòng)初始化為0 作用域:作用域仍為局部作用域 特征 局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲(chǔ)方式即改變了它的生存期。 全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域, 限制了它的使用范圍,2.5.3.3 靜態(tài)函數(shù),定義 在函數(shù)的返回類型前加上關(guān)鍵字static 特性 只是在聲明他的文件當(dāng)中可見,不能被其他文件所用 優(yōu)勢(shì) 其他文件中可以定義相同名

11、字的函數(shù),不會(huì)發(fā)生沖突 靜態(tài)函數(shù)不能被其他文件所用,2.5.3.3 靜態(tài)函數(shù),實(shí)例分析:,/teststatic2.c,teststatic1.c,void display(); static void staticdis(); int main() display(); staticdis(); renturn 0; ,void display() staticdis(); printf(display() has been called n); static void staticdis() printf(staticdis() has been calledn); ,結(jié)果: 文件分別編譯

12、通過,但是連接的時(shí)候找不到函數(shù)staticdis()的定義,2.5.3.4 statics實(shí)例,例:統(tǒng)計(jì)次數(shù)功能,void count(); int main() int i; for (i = 1; i = 3; i+) count(); return 0; void count() static num = 0; num+; printf(I have been called %d,num,timesn); ,結(jié)果: I have been called 1 times. I have been called 2 times. I have been called 3 times.,2.5

13、.4 array_name和 char *p = a; /*運(yùn)行下面這句后, vc6.0 提示的錯(cuò)誤為:cannot convert from char (*)5 to char *, ,結(jié)果: 1245044 1245040 abcd abcd,2.5.4 array_name和 int i,j; a=65535; i=-1; j=a; b=i; printf(unsigned)%u(int)%dn,a,j); printf(int)%d(unsigned)%un,i,b); ,結(jié)果: (unsigned)65535(int)-1 (int)-1(unsigned)65535,2.5.5 強(qiáng)

14、制數(shù)據(jù)類型轉(zhuǎn)換的總結(jié),轉(zhuǎn)換規(guī)則,double float 高 long unsigned Int char,short 低,說明: 橫向箭頭表示必須的轉(zhuǎn)換 縱向箭頭表示當(dāng)運(yùn)算符兩邊的運(yùn)算數(shù)為不同類型時(shí)的轉(zhuǎn)換 低高 形式上改變, 數(shù)據(jù)的實(shí)質(zhì)內(nèi)容 不變 高低 可能有些數(shù)據(jù)丟失,2.5.5 強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換的總結(jié),轉(zhuǎn)換規(guī)則 把賦值運(yùn)算符右側(cè)表達(dá)式的類型轉(zhuǎn)換為左側(cè)變量的類型 轉(zhuǎn)換細(xì)節(jié) 浮點(diǎn)型與整型 單、雙精度浮點(diǎn)型 char型與int型 int型與1ong型 無符號(hào)整數(shù),階段小節(jié),常見的位運(yùn)算符有哪些 什么是數(shù)據(jù)指針 如何定義一個(gè)函數(shù)指針 const有那些特點(diǎn),主要應(yīng)用在哪些方面 static主要有幾

15、種用法,各自特點(diǎn)是什么 C強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)化要注意哪些方面,2.6 C語言編程易犯毛病集合,書寫標(biāo)識(shí)符時(shí),忽略了大小寫字母的區(qū)別 忽略了變量的類型,進(jìn)行了不合法的運(yùn)算 將字符常量與字符串常量混淆 忽略了“=”與“=”的區(qū)別 忘記加分號(hào) 多加分號(hào) 輸入字符的格式與要求不一致 switch語句中漏寫break語句 忽視了while和do-while語句在細(xì)節(jié)上的區(qū)別 定義數(shù)組時(shí)誤用變量,2.6.1書寫標(biāo)識(shí)符時(shí),忽略了大小寫字母的區(qū)別,分析 注意:C認(rèn)為大寫字母和小寫字母是兩個(gè)不同的字符,main() int a=5; printf(%d,A); ,2.6.2 忽略了變量的類型,進(jìn)行了不合法的運(yùn)算,分

16、析 注意:整型變量a和b可以進(jìn)行求余運(yùn)算,而實(shí)型變量則不允許進(jìn)行“求余”運(yùn)算,main() float a,b; printf(%d,a%b); ,2.6.3 將字符常量與字符串常量混淆,分析 char c; c= a; 注意: 字符常量是由一對(duì)單引號(hào)括起來的單個(gè)字符 字符串常量是一對(duì)雙引號(hào)括起來的字符序列 以“”作字符串結(jié)束標(biāo)志,2.6.3 將字符常量與字符串常量混淆,分析 char c; c= a; 注意: 字符常量是由一對(duì)單引號(hào)括起來的單個(gè)字符 字符串常量是一對(duì)雙引號(hào)括起來的字符序列 以“”作字符串結(jié)束標(biāo)志,2.6.4 忽略了“=”與“=”的區(qū)別,分析 if (a=3) a=b; if

17、(a=3) a=b; 注意: “=”是賦值運(yùn)算符 “=”是關(guān)系運(yùn)算符,2.6.5 忘記加分號(hào),分析, a=1 b=2 z=x+y; t=z/100; printf(%f,t); ,2.6.6 多加分號(hào),分析 注意: 復(fù)合語句的花括號(hào)后不應(yīng)再加分號(hào) for (I=0;Iy?x:y; return(z); ,注意 形參應(yīng)該在函數(shù)體外定義 局部變量應(yīng)該在函數(shù)體內(nèi)定義,2.6.13 誤認(rèn)為形參值的改變會(huì)影響實(shí)參的值,語句分析,語句改正,main () int x=3,y=4; swap(x,y); printf (%d,%d,x,y); int swap (int x,int y) int z; z=

18、x;x=y;y=z; ,main () int x=3,y=4; int *p1,*p2; p1= ,注意 實(shí)參和形參之間單向傳遞,2.6.14 函數(shù)的實(shí)參和形參類型不一致,語句分析,錯(cuò)誤分析 C 要求實(shí)參與形參的類型一致 P1 -指針參數(shù) P1 - 整形參數(shù),main () int x=3,y=4; int *P1,*p2; P1= ,2.7 C語言的調(diào)試,如果我運(yùn)行的程序掛起了,應(yīng)該怎么辦 如何檢測(cè)內(nèi)存漏洞(leak) 調(diào)試程序的最好方法是什么 怎樣調(diào)試TSR程序 能報(bào)告條件失敗的程序,2.7.1如果我運(yùn)行的程序掛起了,應(yīng)該怎么辦,程序掛起的四大原因 程序中有死循環(huán); 程序運(yùn)行的時(shí)間比所期

19、望的長; 程序在等待某些輸入信息,并且直到輸入正確后才會(huì)繼續(xù)運(yùn)行; 程序設(shè)計(jì)的目的就是為了延遲一段時(shí)間,或者暫停執(zhí)行。,2.7.1.1死循環(huán),什么死循環(huán) 有幾張情況可以造成死循環(huán) 分析例子: 解決方式 增加對(duì)應(yīng)的調(diào)試debug信息,/* initialize a double dimension array */ for (a = 0 ; a 10; +a ) for(b = 0; b10; +a) arrayab=0; ,2.7.1.2 運(yùn)行時(shí)間比期望的時(shí)間長,什么時(shí)候回出現(xiàn)這種情況 該如何消除 分析例子: /* A subroutine to calculate Fibonacci num

20、bers */ int fib ( int i) if (i 3) return 1; else return fib( i - 1)+fib( i - 2); 解決方式 熟悉基本的語法或者算法運(yùn)算信息,2.7.1.3 等待正確的輸入,原因是:等待正確的輸入信息 分析例子:,# include main() FILE *in = fopen(numbers.dat, r); int total = 0, n; while( fscanf( in, %d , ,2.7.2 如何檢測(cè)內(nèi)存漏洞(leak),什么是內(nèi)存漏洞 動(dòng)態(tài)分配的內(nèi)存單元不再使用卻沒有被釋放 什么情況會(huì)容易出現(xiàn)這樣的問題 忘記釋放

21、分配給臨時(shí)緩沖區(qū)的內(nèi)存空間 內(nèi)存漏洞特點(diǎn) 最難檢測(cè) 最危險(xiǎn),2.7.2 如何檢測(cè)內(nèi)存漏洞(leak),例子分析,void SayHi( char *name ) char * UpName; int a; UpName = malloc( strlen( name ) +1); / * Allocate space for the name * / for( a =0; astrlen( name ); +a) UpNamea = toupper( namea) ; UpName a = 0; printf(Hello, %sin, UpName ); int main() SayHi( Da

22、ve ); return( 0 ); ,2.7.2 如何檢測(cè)內(nèi)存漏洞(leak),解決方案 小心謹(jǐn)慎地編寫程序,充分考慮到內(nèi)存漏洞的可能性 malloc和free要配對(duì) 使用相應(yīng)的軟件包 利用語言的擴(kuò)展功能,2.7.3調(diào)試程序的最好方法是什么,調(diào)試過程的三個(gè)要素 應(yīng)該用什么工具調(diào)試一個(gè)程序? 用什么辦法才能找出程序中的錯(cuò)誤? 怎樣才能從一開始就避免錯(cuò)誤?,2.7.3.1應(yīng)該用什么工具調(diào)試一個(gè)程序,調(diào)試工具功能 觀察程序的運(yùn)行情況 設(shè)置斷點(diǎn) 設(shè)置監(jiān)視,2.7.3.2 用什么辦法才能找出程序中的錯(cuò)誤,先調(diào)試程序中較小的組成部分,然后調(diào)試較大的組成部分 徹底調(diào)試好程序的一個(gè)組成部分后,再調(diào)試下一個(gè)組

23、成部分 連續(xù)地觀察程序流(flow)和數(shù)據(jù)的變化 始終打開編譯程序警告選項(xiàng) 并試圖消除所有警告 準(zhǔn)確地縮小存在錯(cuò)誤的范圍,2.7.3.3 如何從一開始就避免錯(cuò)誤,程序中應(yīng)有足夠的注釋 函數(shù)應(yīng)當(dāng)簡(jiǎn)潔 程序流應(yīng)該清晰,避免使用goto語句和其它跳轉(zhuǎn)語句 函數(shù)名和變量名應(yīng)具有描述性,2.7.4 能報(bào)告條件失敗的程序,assert()命令 打印失敗條件的內(nèi)容; 打印發(fā)生錯(cuò)誤的行號(hào); 打印錯(cuò)誤所在的源文件名; 使程序以出錯(cuò)狀態(tài)結(jié)束。 NDEBUG宏定義,2.7.4 能報(bào)告條件失敗的程序,assert()例子,foo() char * buffer; buffer = malloc( 10000 ); assert ( buffer |= NULL ); float IntFrac(int Num, int Denom ) assert( Denom ! = 0 )

溫馨提示

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

評(píng)論

0/150

提交評(píng)論