版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第8章編譯預(yù)處理及程序調(diào)試鹽城本章主要內(nèi)容8.1編譯預(yù)處理及程序調(diào)試的引入8.2宏定義8.3文件包含8.4條件編譯8.5程序調(diào)試8.6綜合實例
8.1編譯預(yù)處理及程序調(diào)試的引入在前面章節(jié)的源程序中,我們經(jīng)常看到以#include、#define開頭的行,這些代碼的功能是什么?如何利用?初學(xué)者在程序編寫過程中,經(jīng)常出現(xiàn)一些錯誤,如何快速查找錯誤、調(diào)試程序?8.1.1問題與引例
【引例】用函數(shù)的方法求兩個整數(shù)和兩個實數(shù)的最小數(shù)。問題分析:引例要求構(gòu)造函數(shù)求出兩個整型數(shù)據(jù)的最小數(shù)和求出兩個實型數(shù)據(jù)中的最小數(shù)。針對此類問題,必須構(gòu)造兩個不同數(shù)據(jù)類型的函數(shù)才能實現(xiàn)。8.1.1問題與引例8.1編譯預(yù)處理及程序調(diào)試的引入
#include<stdio.h>voidmain(){intintmin(intx,inty);//求整型數(shù)據(jù)最小數(shù)的函數(shù)聲明floatfloatmin(floatx,floaty);//求實型數(shù)據(jù)最小數(shù)的函數(shù)聲明inta,b,mini;floatc,d,minf;scanf("%d,%d",&a,&b);mini=intmin(a,b);//調(diào)用求整型數(shù)據(jù)最小數(shù)的函數(shù)scanf("%f%f",&c,&d);minf=floatmin(c,d);//調(diào)用求實型數(shù)據(jù)最小數(shù)的函數(shù)printf("mixint=%d,minfloat=%f\n",mini,minf);}
程序代碼設(shè)計如下://求整型數(shù)據(jù)最小數(shù)的函數(shù)定義intintmin(intx,inty){return(x<y?x:y);}//求實型數(shù)據(jù)最小數(shù)的函數(shù)定義floatfloatmin(floatx,floaty){return(x<y?x:y);}思考:請比較一下這兩個函數(shù),有何異同?數(shù)據(jù)類型不同其他代碼相同
8.1.2編譯預(yù)處理及程序調(diào)試的概念編譯預(yù)處理——編譯程序?qū)υ闯绦蜻M行正式編譯之前由編譯預(yù)處理程序提前所做的工作,其目的是對程序中的特殊命令作出解釋,以產(chǎn)生新的源程序,對其進行正式編譯。這里所謂的特殊命令就是編譯預(yù)處理命令,這是C語言的特色,具有使程序有良好的可移植性、可調(diào)試性,改善編程環(huán)境的優(yōu)點。C程序編寫完成后,在編譯、連接和運行過程中可能發(fā)生各種錯誤,查找并糾正錯誤程序的過程,稱為程序調(diào)試。
8.1.2編譯預(yù)處理及程序調(diào)試的概念C語言的編譯預(yù)處理命令有宏定義、文件包含和條件編譯三種。宏定義可以簡化C語言源程序的編寫,并具有類似函數(shù)的功能。文件包含命令可以將其他源程序文件包含進來,以簡化重復(fù)編程的工作。條件編譯可以編寫易移植、易調(diào)試的程序,提高程序的執(zhí)行效率。在C語言源程序中允許用一個標(biāo)識符來表示一個字符串,稱為“宏”,被稱為“宏”的標(biāo)識符稱為“宏名”,#define稱為宏定義。編譯預(yù)處理時,對程序中出現(xiàn)的所有“宏名”,都用宏定義中的字符串去替換,這稱為“宏替換”或“宏展開”。宏定義是由源程序中的宏定義命令完成的,宏替換是由預(yù)處理程序自動完成的。在C語言中,“宏定義”分為無參宏定義和有參宏定義兩種。8.2宏定義
8.2宏定義8.2.1無參宏定義
無參宏定義的宏名后不帶參數(shù),用一個宏名標(biāo)識符代表一個字符串,相當(dāng)于一個符號常量。1.無參宏定義一般形式為:#define標(biāo)識符字符串例如:#definePI3.1415926宏定義的作用是在本程序文件中用指定的標(biāo)識符來代替指定的字符串。這里在編譯預(yù)處理時,將程序中在該命令以后出現(xiàn)的所有的PI都用“3.1415926”代替。#include<stdio.h>#definePI3.1415926voidmain(){floatl,s,r,v;printf("inputradius:");scanf("%f",&r);l=2.0*PI*r;s=PI*r*r;v=4.0/3*PI*r*r*r;printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v);}【例1】閱讀下列程序,體會不帶參數(shù)的宏定義功能。8.2.1無參宏定義(1)宏名一般習(xí)慣用大寫字母表示,以便與變量名相區(qū)別。但這并非規(guī)定,也可用小寫字母。(2)使用宏名代替一個字符串,可以減少程序中重復(fù)書寫某些字符串的工作量。(3)宏定義是用宏名代替一個字符串,只作簡單置換,不作正確性檢查。只有在編譯已被宏展開后的源程序時才會發(fā)現(xiàn)語法錯誤并報錯。2.無參宏定義使用說明8.2.1無參宏定義(4)宏定義不是C語句,不必在行末加分號。如果加了分號則會連分號一起進行置換。(5)#define命令出現(xiàn)在程序中函數(shù)的外面,宏名的有效范圍為定義命令之后到本源文件結(jié)束。通常,#define命令寫在文件開頭,函數(shù)之前,作為文件一部分,在此文件范圍內(nèi)有效。(6)可以用#undef命令終止宏定義的作用域。
2.無參宏定義使用說明8.2.1無參宏定義例:#defineG9.8______________voidmain()↑{G的有效范圍
…↓}------------#undefGf1(){…}在f1函數(shù)中,G不再代表9.8。這樣可以靈活控制宏定義的作用范圍。(7)在進行宏定義時,可以引用已定義的宏名,可以層層置換。(8)對程序中用雙撇號括起來的字符串內(nèi)的字符,即使與宏名相同,也不進行置換。(9)宏定義是專門用于預(yù)處理命令的一個專用名詞,它與定義變量的含義不同,只作字符替換,不分配內(nèi)存空間。2、無參宏定義使用說明#include<stdio.h>#defineR3.0#definePI3.1415926#defineL2*PI*R#defineSPI*R*Rvoidmain(){printf("L=%f\nS=%f\n",L,S);}運行情況如下:L=18.849556S=28.274333【例2】
在宏定義中引用已定義的宏名。
2.無參宏定義使用說明
8.2.2有參宏定義
C語言允許宏帶有參數(shù),稱為有參宏定義。宏定義中的參數(shù)稱為形式參數(shù),宏調(diào)用中的參數(shù)稱為實際參數(shù)。在調(diào)用中,不僅要宏展開,還要用實參去替換形參。(1)有參宏定義
有參宏定義一般形式為:#define
宏名(參數(shù)表)字符串
1.有參宏的定義與調(diào)用例如:#defineMAX(x,y)x>y?x:y//有參宏定義
#defineMPLUS(x,y)((x)*(y))
8.2.2有參宏定義
(2)有參宏調(diào)用有參宏調(diào)用的一般形式:宏名(實參表);
1.有參宏的定義與調(diào)用例如:m=MAX(3,5);p=MPLUS(3,5);//宏調(diào)用
8.2.2有參宏定義
1.有參宏的定義與調(diào)用(3)執(zhí)行過程程序中如果有帶實參的宏,則按#define命令行中指定的字符串從左到右進行置換。如果字符串中包含宏中的形參(如x,y),則將程序語句中相應(yīng)的實參(可以是常量、變量或表達式)代替形參,而字符串中的其他字符則原樣保留。#defineN5+6#defineMN*N#defineM1(x)x*x#defineM2(x,y)x*yvoidmain(){printf(”%d\n”,M);printf(”%d\n”,M1(5-2));printf(”%d\n”,M2(6-1,2-1));}【例3】
分析下列程序的功能?!纠?】
分析程序中的for循環(huán)執(zhí)行的次數(shù)。#include<stdio.h>#defineN2#defineMN+1#defineNUM(M+1)*M/2voidmain(){inti;for(i=1;i<=NUM;i++)printf("%d\n",i); }(1)對帶參數(shù)的宏展開只是將語句中的宏名后面括號內(nèi)的實參字符串代替#define命令行中的形參。(2)在宏定義時,在宏名與帶參數(shù)的括弧之間不應(yīng)加空格,否則將空格以后的字符都作為替代字符串的一部分。說明:(1)函數(shù)調(diào)用時,先求出實參表達式的值,然后代入形參。而使用帶參的宏只是進行簡單的字符替換。(2)函數(shù)調(diào)用是在程序運行時處理的,為形參分配臨時的內(nèi)存單元。而宏展開則是在編譯前進行的,在展開時并不分配內(nèi)存單元,不進行值的傳遞處理,也沒有“返回值”的概念。(3)對函數(shù)中的實參和形參類型要求一致。而宏名無類型,它的參數(shù)也無類型,只是一個符號代表,展開時代入指定的字符串即可。宏定義時,字符串可以是任何類型的數(shù)據(jù)。(4)調(diào)用函數(shù)只可得到一個返回值,而用宏可以設(shè)法得到幾個結(jié)果。帶參數(shù)的宏和函數(shù)的區(qū)別:(5)使用宏次數(shù)多時,宏展開后源程序長,而函數(shù)調(diào)用不會使源程序變長。(6)宏替換不占運行時間,只占編譯時間。而函數(shù)調(diào)用則占運行時間(分配單元、保留現(xiàn)場、值傳遞、返回)。帶參數(shù)的宏和函數(shù)的區(qū)別:如果善于利用宏定義,可以實現(xiàn)程序的簡化,如事先將程序中的“輸出格式”定義好,以減少在輸出語句中每次都要寫出具體的輸出格式的麻煩。所謂“文件包含”處理是指一個源文件可以包含另外一個源文件的全部內(nèi)容,以提高代碼的重用性。C語言提供了#include命令用來實現(xiàn)“文件包含”的操作。一般形式為:#include"文件名"或#include<文件名>8.3文件包含
注意:
在編譯時并不是分別對兩個文件分別進行編譯,然后再將它們的目標(biāo)程序連接的,而是在經(jīng)過編譯預(yù)處理后將頭文件format.h包含到主文件中,得到一個新的源程序,然后對這個文件進行編譯,得到一個目標(biāo)(.obj)文件。被包含的文件成為新的源文件的一部分,而單獨生成目標(biāo)文件。8.3文件包含1.#include命令行通常書寫在所用文件的最開始部分,所以有時也把包含文件稱做“頭文件”。頭文件名可以由用戶指定,其后綴不一定用“.h”。2.當(dāng)包含文件被修改后,對包含該文件的源程序必須重新進行編譯連接,這樣才會使修改后的文件生效。3.文件包含允許嵌套,即在一個被包含文件中又可以包含另外的文件。4.一個#include命令只能包含一個頭文件,若有多個文件要包含,則需要多個#include命令,且必須一行一條,行尾不允許有分號。幾點說明:8.3文件包含
8.4條件編譯所謂“條件編譯”,是對部分內(nèi)容指定編譯的條件,使其只在滿足一定條件才進行編譯。條件編譯命令的幾種形式:(1)#ifdef標(biāo)識符程序段1#else
程序段2#endif(2)#ifndef標(biāo)識符程序段1#else
程序段2#endif(3)#if表達式程序段1#else
程序段2#endif8.5程序調(diào)試
一個C程序編寫完成后,在編譯、連接和運行過程中可能發(fā)生各種錯誤,因此,還應(yīng)對程序進行調(diào)試和測試,盡可能發(fā)現(xiàn)錯誤并予以糾正。
只有當(dāng)程序正確無誤地運行時,程序才編制完成。查找并糾正程序錯誤的過程稱為調(diào)試,程序調(diào)試是程序開發(fā)過程中的一個不可缺少的環(huán)節(jié),需要通過實踐積累提高。8.5.1程序的錯誤類型C語言程序的錯誤類型主要有5種:編譯錯誤、編譯警告、鏈接錯誤、運行錯誤和邏輯錯誤。8.5.1程序的錯誤類型編譯錯誤(error):是在編譯過程中發(fā)現(xiàn)的錯誤,通常屬于語法錯誤。編譯警告(warning):是在編譯過程中發(fā)現(xiàn)的、可能存在的潛在錯誤。鏈接錯誤:發(fā)生在將用戶程序的目標(biāo)代碼與用戶程序引用的庫函數(shù)的目標(biāo)代碼鏈接,生成可執(zhí)行代碼的過程中。邏輯錯誤:發(fā)生在程序運行階段,程序無語法錯誤,也能正常運行,但程序運行結(jié)果不正確。運行錯誤:有時程序既無語法錯誤,又無邏輯錯誤,但程序不能正常運行或結(jié)果不對。8.5.2編譯與連接錯誤的查看與修改1.編譯錯誤的查看與修改編譯的目的是將C源程序轉(zhuǎn)換為機器指令代碼。在編譯過程中,如果遇到程序中有語法錯誤,則在集成開發(fā)環(huán)境底部的輸出窗口中顯示相應(yīng)的錯誤信息,提示程序員修改程序。2.連接錯誤的查看與修改在連接階段也可能出現(xiàn)一些錯誤提示,但由于連接的對象是目標(biāo)程序,它并不指出錯誤發(fā)生的詳細位置,不容易確定錯誤的準(zhǔn)確位置。注意:在找到連接錯誤并改正后,一定要重新編譯后才能再次連接。8.5.3運行與邏輯錯誤的判斷與調(diào)試運行錯誤是在程序運行時發(fā)生的,編譯和連接過程均正常,當(dāng)運行時表現(xiàn)為突然終止程序運行、死循環(huán)、死機、自動重啟或者輸出信息混亂等。與編譯錯誤相比,運行階段的錯誤更難查找和判斷,原因是很少或根本沒有提示信息。注意:在找到連接錯誤并改正后,一定要重新編譯后才能再次連接?!纠?.6】分析下列程序,根據(jù)不同數(shù)據(jù)檢測有無錯誤。#include<stdio.h>voidmain(){inta,b,c;scanf(”%d,%d”,&a,&b);c=a/b;printf(”%d\n”,c);}b為非零值和零值均測試1.靜態(tài)檢查在編寫好程序并保存后,首先要進行人工檢查,盡可能養(yǎng)成嚴謹?shù)目茖W(xué)作風(fēng),對每一步進行把關(guān),以避免由于疏忽而造成的錯誤。為了更有效地進行人工檢查,編寫的程序應(yīng)力求做到如下幾點:(1)采用結(jié)構(gòu)化程序方法編程,以增加可讀性;(2)盡可能增加注釋,以便于理解;(3)對復(fù)雜程序,盡可能用不同函數(shù)實現(xiàn)單獨功能,在主函數(shù)中調(diào)用等。8.5.4程序調(diào)試的步驟2.動態(tài)檢查靜態(tài)檢查無誤后,再進行動態(tài)檢查(程序調(diào)試)。由編譯系統(tǒng)進行檢查,發(fā)現(xiàn)錯誤的過程稱為動態(tài)檢查。在編譯時可根據(jù)語法錯誤的提示信息進行修改并重新編譯。8.5.4程序調(diào)試的步驟對于運行階段的錯誤,有以下幾種調(diào)試手段:標(biāo)準(zhǔn)數(shù)據(jù)校驗:用若干組已知結(jié)果的標(biāo)準(zhǔn)數(shù)據(jù)對程序進行檢驗。程序跟蹤:讓程序一句一句執(zhí)行,通過觀察和分析程序執(zhí)行過程中數(shù)據(jù)和程序執(zhí)行流程的變化來查找錯誤。邊界檢查:在設(shè)計檢驗數(shù)據(jù)時,應(yīng)重點檢驗邊界和特殊情況。簡化循環(huán)次數(shù):調(diào)試時為加快調(diào)試速度,可對程序適當(dāng)做些簡化。如減少循環(huán)次數(shù)、縮小數(shù)組規(guī)模、屏蔽某些次要程序段等。8.5.4程序調(diào)試的基本手段【例8.7】利用海倫公式求三角形面積,其中三條邊長a,b,c從鍵盤上輸入。8.6綜合實例(1)算法分析程序主要完成以下任務(wù):輸入三條邊長a,b,c;根據(jù)輸入的a,b,c的值判斷能否組成三角形,若能組成三角形,利用海倫公式求三角形面積,其中p=(a+b+c)/2.0;判斷能否組成三角形的條件是任意兩邊之和大于第三邊。(2)程序代碼#include<stdio.h>#include<math.h>voidmain(){ floata,b,c,p,area,x; printf("請輸入三個數(shù):"); scanf("%f%f%f",&a,&b,&c); if(a+b>c&&b+c>a&&a+c>b) {p=(a+b+c)/2.0; x=(p*(p-a)*(p-b)*(p-c)); if(x<0) x=-x; area=sqrt(x); printf("area=%6.2f\n",area); } else printf("dataerror\n");}(3)程序調(diào)試調(diào)試運行程序時,所取的測試數(shù)據(jù)為分支結(jié)構(gòu)中不同條件的數(shù)據(jù),以保證每個分支都有可能被執(zhí)行。第一次運行
請輸入三個數(shù):345area=6.000000第二次運行
請輸入三個數(shù):123dataerror8.6綜合實例【例8.9】用單步執(zhí)行程序的方法演示下列循環(huán)的執(zhí)行過程。(1)給定如下源程序代碼#include<stdio.h>voidmain(){inti,//循環(huán)控制變量
start,/
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 調(diào)研報告:全球及中國新型穿戴設(shè)備市場全景圖譜 出貨量穩(wěn)定增長
- 《工作與健康》課件
- 單位管理制度展示大全【人力資源管理篇】十篇
- 單位管理制度展示大合集【人力資源管理】十篇
- 策略深度報告:1月度金股春季躁動的“科技成長”和“內(nèi)循環(huán)”
- 【大學(xué)課件】市場競爭策略
- 特種設(shè)備安全管理人員和操作人員培訓(xùn)課件
- 2025年中國碘佛醇注射液行業(yè)發(fā)展?jié)摿Ψ治黾巴顿Y戰(zhàn)略咨詢報告
- 中國可信計算機行業(yè)發(fā)展趨勢預(yù)測及投資戰(zhàn)略咨詢報告
- 穿墻螺栓行業(yè)市場發(fā)展及發(fā)展趨勢與投資戰(zhàn)略研究報告
- 鈷酸鋰結(jié)構(gòu)特性
- 臺州造船行業(yè)產(chǎn)值分析
- 2024年度醫(yī)院兒童保健科醫(yī)務(wù)人員述職報告課件
- 品牌部工作總結(jié)匯報
- 全麻病人蘇醒期躁動的原因及處理課件
- VTE評估及護理預(yù)防
- 2024全新誠信考試課件
- 2024年大學(xué)生心理健康教育考試題庫及答案(含各題型)
- 《全腦速讀記憶講座》課件
- 上海市產(chǎn)業(yè)園區(qū)規(guī)劃及招商引資策略研究報告目錄
- 小兒預(yù)防接種過敏性休克
評論
0/150
提交評論