第8章預(yù)處理命令_第1頁
第8章預(yù)處理命令_第2頁
第8章預(yù)處理命令_第3頁
第8章預(yù)處理命令_第4頁
第8章預(yù)處理命令_第5頁
已閱讀5頁,還剩20頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第8章預(yù)處理命令本章概述本章的學(xué)習(xí)目標(biāo)主要內(nèi)容本章概述介紹宏定義的兩種形式,介紹文件包含的使用方法,介紹條件編譯的概念。第8章預(yù)處理命令本章的學(xué)習(xí)目標(biāo):

本章教學(xué)目的:掌握宏定義的兩種形式,掌握文件包含的使用方法了解條件編譯的概念。

本章教學(xué)重點(diǎn):宏定義的兩種形式,文件包含的使用方法。

本章教學(xué)難點(diǎn):帶參數(shù)的宏定義。第8章預(yù)處理命令第8章預(yù)處理命令8.1宏定義8.2“文件包含”處理8.3條件編譯8.4本章小結(jié)主要內(nèi)容:

編譯預(yù)處理是指一些行首以#開頭的特殊語句,必須在對(duì)程序進(jìn)行通常的編譯之前,先對(duì)程序中這些特殊的命令進(jìn)行“預(yù)處理”,即根據(jù)預(yù)處理命令對(duì)程序作相應(yīng)的處理(例如,若程序中用#define命令定義了一個(gè)符號(hào)常量A,則在預(yù)處理時(shí)將程序中所有的A都置換為指定的字符串)。

經(jīng)過預(yù)處理后程序不再包括預(yù)處理命令了,最后再由編譯程序?qū)︻A(yù)處理后的源程序進(jìn)行通常的編譯處理,得到可供執(zhí)行的目標(biāo)代碼。

C語言與其它高級(jí)語言的一個(gè)重要區(qū)別是可以使用預(yù)處理命令和具有預(yù)處理的功能。第8章預(yù)處理命令C提供的預(yù)處理功能主要有以下三種:

宏定義、文件包含和條件編譯它們分別用宏定義命令、文件包含命令和條件編譯命令來實(shí)現(xiàn)。為了與一般C語句相區(qū)別,這些命令以符號(hào)“?!遍_頭。8.1宏定義

宏定義指的是用#define定義的命令行,有不帶參數(shù)和帶參數(shù)兩種形式。

8.1.1不帶參數(shù)的宏定義

不帶參數(shù)的宏定義的一般形式為:

#define標(biāo)識(shí)符

字符串

含義是用指定的宏名(即標(biāo)識(shí)符)來代表其后字符串。

例如:

#defineSIZE10000

#definePI3.1415926

#defineFORMAT“%d,%d,%d\n”作用是指用標(biāo)識(shí)符SIZE來代替字符串“10000”,用標(biāo)識(shí)符PI來代替字符串“3.1415926”,用標(biāo)識(shí)符FORMAT來代替字符串“

“%d,%d,%d\n”

”,

在編譯預(yù)處理時(shí),將程序中在該命令以后出現(xiàn)的所有的SIZE用10000代替、PI用3.1415926代替、FORMAT用“%d,%d,%d\n”代替。這種方法使用戶能以一個(gè)簡單的名字代替一個(gè)長的字符串,可以減小重復(fù)編程工作量,而且不容易出錯(cuò)。

把定義時(shí)所用的標(biāo)識(shí)符稱為“宏名”,即SIZE、PI和FORMAT都是宏名。在預(yù)編譯時(shí)將宏名替換成字符串的過程稱為“宏展開”。

注意:

宏名習(xí)慣用大寫字母表示。定義宏與定義變量含義不同,宏定義只是作字符替換,并不給宏名分配內(nèi)存空間。

例8.1使用宏來計(jì)算若干個(gè)數(shù)組元素的和。

#include<stdio.h>#defineSIZE100intmain(){inti,sum=0;intdata[SIZE];for(i=0;i<SIZE;i++)

{scanf(“%d”,&data[i]);

sum=sum+data[i];

}printf(“sum=%d\n”,sum);return0;}運(yùn)行此程序可計(jì)算100個(gè)數(shù)組元素值的總和。對(duì)宏定義的說明:

(1)定義宏的目的是提高程序的可讀性和通用性,便于程序的修改。例如若要把例8.1中數(shù)組data的元素個(gè)數(shù)改變?yōu)?00,則只要將“#defineSIZE100”改為“#defineSIZE200”即可,程序中的其它語句均不用修改。

(2)不要在宏定義的行末加分號(hào),因?yàn)楹甓x不是C語句,加分號(hào)后,會(huì)將分號(hào)也作為字符串的組成部分,宏展開后可能出現(xiàn)錯(cuò)誤。

(3)宏定義可以出現(xiàn)在程序的任何位置,一般位于文件開頭,寫在函數(shù)的外面。宏名的有效范圍是從定義處到本源文件結(jié)束??梢杂?undef命令終止宏定義的作用域。例如:

#definePI3.1415926

intmain()

{…

#undefPI

}

由于#undef的作用,使PI的作用范圍在#undef行處終止。若在#undefPI之后再出現(xiàn)PI,則是無效的。

(4)宏定義是用宏名代替一個(gè)字符串,凡在宏定義有效范圍內(nèi)的宏名都用該字符串代替,但要注意:雙引號(hào)內(nèi)的與宏名相同的字符串不認(rèn)為是宏名,不進(jìn)行替換。例如:

#defineYES1

printf(“YES”);

程序?qū)@示YES,而不是1。

(5)可以引用前面已經(jīng)定義的宏名來定義新的宏,例如:

#defineI130

#defineI260

#defineJI1+I2

#defineKJ*2+J/2+I2這里J引用了I1和I2,K引用了J和I2。

注意K展開是:30+60*2+30+60/2+60,

不要以為是:(30+60)*2+(30+60)/2+60。

除非前面的定義是:#defineJ(I1+I2)。8.1.2帶參數(shù)的宏定義

帶參數(shù)的宏定義的一般形式為:

#define標(biāo)識(shí)符(形參表)字符串

帶參數(shù)的宏展開時(shí),還要進(jìn)行參數(shù)替換。宏定義中形參表中的形參,在程序中將用實(shí)參替換。例如:

#definePI3.14159

#defineV(r)4*PI*r*r*r/3

V(r)為帶參數(shù)的宏,例如在程序中使用V(6)時(shí),是用6代替宏定義中的形式參數(shù)r,V(6)展開為:4*3.14159*6*6*6/3,這是用來計(jì)算半徑為6的球的體積。

例8.2使用帶參數(shù)的宏計(jì)算梯形面積。

#include<stdio.h>

#defineS(a,b,h)(a+b)*h/2

intmain()

{intc1=6,c2=8,c3=10;

printf(“S=%d\n”,S(c1,c2,c3));

return0;

}S(c1,c2,c3)展開為:(c1+c2)*c3/2。程序?qū)嶋H執(zhí)行的是下面的輸出語句:printf(“S=%d\n”,(c1+c2)*c3/2);

如果將上面的S(c1,c2,c3)換成S(6,c2,2+8),運(yùn)行程序后,輸出結(jié)果還是70嗎?

在使用帶參數(shù)的宏定義時(shí),宏名和括號(hào)之間不能有空格,否則系統(tǒng)會(huì)把括號(hào)、形參和字符串認(rèn)為是一個(gè)字符串。

例如,如果有

#defineS(x,y)x*y

會(huì)被認(rèn)為:

S是符號(hào)常量(不帶參的宏名),它代表字符串“(x,y)x*y”。

上面介紹的用帶參數(shù)的宏求球的體積和梯形的面積等問題顯然也可以用函數(shù)解決。

帶參數(shù)的宏和函數(shù)在形式上有相似的地方,但是它們有許多不同點(diǎn):

(1)宏展開是在編譯時(shí)進(jìn)行的,不占用程序運(yùn)行時(shí)間,在展開時(shí)并不分配內(nèi)存單元,即使是帶參數(shù)的宏也不分配內(nèi)存單元;而函數(shù)調(diào)用則是在程序運(yùn)行時(shí)進(jìn)行處理的,占用程序運(yùn)行時(shí)間,要為形參分配臨時(shí)的內(nèi)存單元。

(2)宏展開只是替換;而函數(shù)調(diào)用時(shí),要計(jì)算實(shí)參表達(dá)式的值后傳遞給形參,不是替換。函數(shù)調(diào)用時(shí)存在著從實(shí)參向形參傳遞數(shù)據(jù)的過程,而使用帶參數(shù)的宏,也不存在傳遞數(shù)據(jù)的過程。

(3)宏名以及它的參數(shù)都不存在類型問題,展開時(shí)用指定的字符串替換即可。而函數(shù)中的實(shí)參和形參都要定義類型。

(4)宏展開后對(duì)源程序長度有影響,而函數(shù)調(diào)用對(duì)源程序長度無影響。

有些問題,用宏和函數(shù)都可以,如下例:用函數(shù):max(intx,inty){return(x>y)?x:y;}main(){inta,b,c,d,t;……t=max(a+b,c+d);……}用宏:#defineMAX(x,y)(x)>(y)?(x):(y)main(){inta,b,c,d,t;……t=MAX(a+b,c+d);……}

賦值語句展開后為

t=(a+b)>(c+d)?(a+b):(c+d);8.2“文件包含”處理

C語言提供了#include命令用來實(shí)現(xiàn)“文件包含”的操作。作用是將一個(gè)源文件的全部內(nèi)容包含進(jìn)另一個(gè)源文件中來。被包含的文件可以是C語言源文件、庫函數(shù)頭文件等。因?yàn)?include命令行通常都放在文件的開頭,所以這些被包含的文件通常被稱為“標(biāo)題文件”或“頭文件”,常以“.h”(h為head的縮寫)為文件的擴(kuò)展名。當(dāng)然也可以用其他文件擴(kuò)展名,但無論用什么擴(kuò)展名,這個(gè)被包含文件必須是文本文件。

C集成環(huán)境為用戶提供了很多庫函數(shù),每一個(gè)庫函數(shù)都有自己對(duì)應(yīng)的頭文件,在C語言庫函數(shù)與用戶程序之間進(jìn)行信息通信時(shí),要使用一些庫函數(shù)中定義的數(shù)據(jù)和變量,在使用某一庫函數(shù)時(shí),都要在程序中使用#include命令將該函數(shù)所對(duì)應(yīng)的頭文件包含進(jìn)來,否則,程序在編譯時(shí)報(bào)錯(cuò)。

文件包含的使用格式為:#include“文件名”

#include<文件名>

其中的“文件名”和<文件名>的區(qū)別是:當(dāng)使用“文件名”

形式時(shí),預(yù)處理程序首先檢索當(dāng)前文件目錄是否有該文件,如果沒有,再檢索C編譯系統(tǒng)中指定的目錄;而使用<文件名>形式時(shí),預(yù)處理程序直接檢索C編譯系統(tǒng)指定的目錄。使用“文件名”形式時(shí),文件名的前面可添加路徑。例如:#include“d:\tc\include\stdio.h”

常用的標(biāo)準(zhǔn)庫頭文件的擴(kuò)展名都是h,如:#include<stdio.h>/*標(biāo)準(zhǔn)輸入輸出函數(shù)文件*/#include<string.h>/*字符串函數(shù)文件*/#include<ctype.h>/*字符函數(shù)文件*/#include<math.h>/*數(shù)學(xué)函數(shù)庫文件*/

“文件包含”命令可以節(jié)省程序設(shè)計(jì)人員的勞動(dòng)。例如,可以將經(jīng)常使用一組固定的符號(hào)常量(g=9.81,pi=3.1415926,e=2.718等等)用宏定義命令組成一個(gè)文件,只要用#include命令這個(gè)文件包含到自己所寫的源文件中即可。正確的使用#include語句,將會(huì)減少不必要的重復(fù)工作,提高編程效率。特別是在一個(gè)軟件開發(fā)小組共同協(xié)作開發(fā)大型軟件時(shí),include文件十分有用,利用它可以定義程序中共同的常量、函數(shù)原型、宏等,這樣可以便于修改且不易出錯(cuò)。例8.3編制如下內(nèi)容的被包含文件,該文件名為bj.h。#defineSWAP(x,y)t=x;x=y;y=t#defineMAX(x,y)x>y?x:y#defineNUM1(x,y)(x+y)/2#defineNUM2(x,y)sqrt(x+y)編寫另一個(gè)程序file.c,內(nèi)容如下:#include<stdio.h>#include<math.h>#include"bj.h"intmain(){floatt,x=567,y=123;printf("x=%f,y=%f\n",x,y);SWAP(x,y);printf("x=%f,y=%f\n",x,y);printf("x與y的最大值是%f\n",MAX(x,y));printf("x與y的算數(shù)平均值是%f\n",NUM1(x,y));printf("x與y的幾何平均值是%f\n",NUM2(x,y));return0;}執(zhí)行程序file.c,結(jié)果顯示如下:doubleMAX=500.000000longMAX=37編譯并執(zhí)行程序file.c,結(jié)果如下:x=567.000000,y=123.000000x=123.000000,y=567.000000x與y的最大值是567.000000x與y的算數(shù)平均值是345.000000x與y的幾何平均值是26.267851

注意:在編譯時(shí)并不是作為兩個(gè)文件進(jìn)行連接的,而是作為一個(gè)源程序編譯,得到一個(gè)目標(biāo)(.obj)文件。說明:

(1)如果要包含n個(gè)文件,必須用n個(gè)include命令。即一個(gè)include命令只能指定一個(gè)被包含文件。

(2)假設(shè)“wj1.c”、“wj2.c”、“wj3.c”是三個(gè)不同的文件,若在“wj1.c”有如下兩行命令:

#include<wj3.c>

#include<wj2.c>則在文件“wj1.c”中可以用“wj2.c”和“wj3.c”的內(nèi)容,在文件“wj2.c”

中可以用“wj3.c”的內(nèi)容,不必在文件“wj2.c”

中再使用“#include<wj3.c>”命令。

若在“wj1.c”

中只有“#include

<wj2.c>”

命令,而“wj1.c”中又要使用“wj3.c”的內(nèi)容,也可以讓“wj2.c”中出現(xiàn)“#include<wj3.c>”

命令。即文件包含可以嵌套使用。

例8.4分析下面程序的執(zhí)行情況。/*file.c*/#include<stdio.h>#include"myfile.txt"intmain(){fun();return0;}myfile.txt文本文件的內(nèi)容如下:voidfun(){charc;if((c=getchar())!='\n'){putchar(c);fun();}}

在編譯file.c時(shí),預(yù)處理過程中用myfile.txt文件的文本替換file.c中的#include“myfile.txt”,因此本例程序功能是接受用戶的按鍵,直到按回車鍵為止,然后將字符序列顯示出來。8.3條件編譯有時(shí)希望當(dāng)滿足某條件時(shí)對(duì)一組語句進(jìn)行編譯,而當(dāng)條件不滿足時(shí)則編譯另一組語句,使得同一個(gè)源程序在不同的編譯條件下能夠產(chǎn)生不同的目標(biāo)代碼文件。這就是“條件編譯”。

條件編譯命令有以下3種形式:1、#ifdef標(biāo)識(shí)符

程序段1#else

程序段2#endif

作用:當(dāng)標(biāo)識(shí)符已經(jīng)被定義過(一般是用define命令定義),則對(duì)程序段1進(jìn)行編譯;否則編譯程序段2。

其中(#else程序段2)可以沒有。作用:若標(biāo)識(shí)符未被定義,則編譯程序段1;否則編譯程序段2。2、#ifndef標(biāo)識(shí)符

溫馨提示

  • 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)論