2010年高級(jí)語言程序設(shè)計(jì)知識(shí)點(diǎn)總結(jié)(9)
9.1 宏定義
宏定義有無參數(shù)宏定義和帶參數(shù)宏定義兩種。
無參數(shù)的宏定義的一般形式為
# define 標(biāo)識(shí)符 字符序列
其中# define之后的標(biāo)識(shí)符稱為宏定義名(簡稱宏名),要求宏名與字符序列之間用空格符分隔。這種宏定義要求編譯預(yù)處理程序?qū)⒃闯绦蛑须S后所有的定名的出現(xiàn)(注釋與字符串常量中的除外)均用字符序列替換之。前面經(jīng)常使用的定義符號(hào)常量是宏定義的最簡單應(yīng)用。如有:
# define TRUE 1轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
# define FALSE 0
則在定義它們的源程序文件中,凡定義之后出現(xiàn)的單詞TRUE將用1替代之;出現(xiàn)單詞FALSE將用0替代之。
在宏定義的#之前可以有若干個(gè)空格、制表符,但不允許有其它字符。宏定義在源程序中單獨(dú)另起一行,換行符是宏定義的結(jié)束標(biāo)志。如果一個(gè)宏定義太長,一行不夠時(shí),可采用續(xù)行的方法。續(xù)行是在鍵人回車符之前先鍵入符號(hào)“\”。注意回車要緊接在符號(hào)“\”之后,中間不能插入其它符號(hào)。
宏定義的有效范圍稱為宏定義名的轄域,轄域從宏定義的定義結(jié)束處開始到其所在的源程序文件末尾。宏定義名的轄域不受分程序結(jié)構(gòu)的影響??梢杂妙A(yù)處理命令#undef終止宏定義名的轄域。
在新的宏定義中,可以使用前面已定義的宏名。例如,
# define R 2.5
# define PI 3.1415926
# define Circle 2*PI*R
# define Area PI* R * R
程序中的Circle被展開為2*3.1415926* 2.5, Area被展開為3.1415926*2.5*2.5.
如有必要,宏名可被重復(fù)定義。被重復(fù)定義后,宏名原先的意義被新意義所代替。
通常,無參數(shù)的宏定義多用于定義常量。程序中統(tǒng)一用宏名表示常量值,便于程序前后統(tǒng)一,不易出錯(cuò),也便于修改,能提高程序的可讀性和可移植性。特別是給數(shù)組元素個(gè)數(shù)一個(gè)宏定義,并用宏名定義數(shù)組元素個(gè)數(shù)能部分彌補(bǔ)數(shù)組元素個(gè)數(shù)固定的不足。
注意:預(yù)處理程序在處理宏定義時(shí),只作字符序列的替換工作,不作任何語法的檢查。如果宏定義不當(dāng),錯(cuò)誤要到預(yù)處理之后的編譯階段才能發(fā)現(xiàn)。宏定義以換行結(jié)束,不需要分號(hào)等符號(hào)作分隔符。如有以下定定義:轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
# define PI 3.1415926;
原希望用PI求圓的周長的語句
c=2*PI*r;
經(jīng)宏展開后,變成
c=2*3.1415926*r;
這就不能達(dá)到希望的要求。
帶參數(shù)宏定義進(jìn)一步擴(kuò)充了無參數(shù)宏定義的能力,在字符序列替換同時(shí)還能進(jìn)行參數(shù)替換。帶參數(shù)定定義的一般形式為
# define 標(biāo)識(shí)符(參數(shù)表)字符序列
其中參數(shù)表中的參數(shù)之間用逗號(hào)分隔,字符序列中應(yīng)包含參數(shù)表中的參數(shù)。在定義帶參數(shù)的宏時(shí),宏名標(biāo)識(shí)符與左圓括號(hào)之間不允許有空白符,應(yīng)緊接在一起,否則變成了無參數(shù)的宏定義。如有宏定義:
# define MAX(A,B) ((A) > (B)?(A):(B))
則代碼 y= MAX( p+q, u+v)將被替換成 y=((p+q) >(u+v)?(p+q):(u+v)。
程序中的宏調(diào)用是這樣被替換展開的,分別用宏調(diào)用中的實(shí)在參數(shù)字符序列(如p+q和u+V) 替換宏定義字符序列中對(duì)應(yīng)所有出現(xiàn)的形式參數(shù)(如用p+q替代所有形式參數(shù)A,用u+V替代所有形式參數(shù)B),而宏定義字符序列中的不是形式參數(shù)的其它字符則保留。這樣形成的字符序列,即為宏調(diào)用的展開替換結(jié)果。宏調(diào)用提供的實(shí)在參數(shù)個(gè)數(shù)必須與宏定義中的形式參數(shù)個(gè)數(shù)相同。
注意:宏調(diào)用與函數(shù)調(diào)用的區(qū)別。函數(shù)調(diào)用在程序運(yùn)行時(shí)實(shí)行,而宏展開是在編譯的預(yù)處理階段進(jìn)行;函數(shù)調(diào)用占用程序運(yùn)行時(shí)間,宏調(diào)用只占編譯時(shí)間;函數(shù)調(diào)用對(duì)實(shí)參有類型要求,而宏調(diào)用實(shí)在參數(shù)與宏定義形式參數(shù)之間沒有類型的概念,只有字符序列的對(duì)應(yīng)關(guān)系。函數(shù)調(diào)用可返回一個(gè)值,宏調(diào)用獲得希望的C代碼。另外,函數(shù)調(diào)用時(shí),實(shí)參表達(dá)式分別獨(dú)立求值在前,執(zhí)行函數(shù)體在后。宏調(diào)用是實(shí)在參數(shù)字符序列替換形式參數(shù)。替換后,實(shí)在參數(shù)字符序列就與相鄰的字符自然連接,實(shí)在參數(shù)的獨(dú)立性就不一定依舊存在。如下面的宏定義:
# define SQR(x) x*x
希望實(shí)現(xiàn)表達(dá)式的平方計(jì)算。對(duì)于宏調(diào)用
P=SQR(y)
能得到希望的宏展開p= y*y.但對(duì)于宏調(diào)用q=SQR(u+v)得到的宏展開是q=u+V*u+V.顯然,后者的展開結(jié)果不是程序設(shè)計(jì)者所希望的。為能保持實(shí)在參數(shù)替換后的獨(dú)立性,應(yīng)在宏定義中給形式參數(shù)加上括號(hào)。進(jìn)一步,為了保證宏調(diào)用的獨(dú)立性,作為算式的宏定義也應(yīng)加括
號(hào)。如 SQR宏定義改寫成:
# define SQR((x)*(x))
才是正確的宏定義。轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
對(duì)于簡短的表達(dá)式計(jì)算函數(shù),或?yàn)榱颂岣叱绦虻膱?zhí)行效率、避免函數(shù)調(diào)用時(shí)的分配存儲(chǔ)單元、保留現(xiàn)場、參數(shù)值傳遞、釋放存儲(chǔ)單元等工作??蓪⒑瘮?shù)定義改寫成宏定義。所以合理使用宏定義,可以使程序更簡潔。
9.2 文件包含
文件包含預(yù)處理命令(簡稱文件包含命令)實(shí)現(xiàn)將指定文件的內(nèi)容作為當(dāng)前源程序的一部分。文件包含預(yù)處理命令的一般形式為
# include “文件名”。
或
# include<文件名>
文件包含命令為組裝大程序和程序文件復(fù)用提供了一種手段。在編寫程序時(shí),習(xí)慣將公共的常量定義、數(shù)據(jù)類型定義和全局變量的外部說明構(gòu)成一個(gè)源文件。稱這類沒有執(zhí)行代碼的文件為頭文件,并以“。h”為文件名的后綴。其它程序文件凡要用到頭文件中定義或說明的程序?qū)ο髸r(shí),就用文件包含命令使它成為自己的一部分。這樣編程的好處是各程序文件使用統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)和常量,能保證程序的一致性,也便于修改程序。頭文件如同標(biāo)準(zhǔn)零件一樣被其它程序文件使用,減少了重復(fù)定義的工作量。
9.3 條件編譯
條件編譯是指在編譯一個(gè)源程序文件時(shí),其中部分代碼段能根據(jù)條件成立與否有選擇地被編譯。即編譯程序只編譯沒有條件或條件成立的代碼段,而不編譯不滿足條件的代碼段。
條件編譯為組裝與環(huán)境有關(guān)的大程序提供有力的支持,能提高程序的可移植性和可維護(hù)性。通常在研制程序系統(tǒng)時(shí),設(shè)計(jì)者將所有與環(huán)境有關(guān)的內(nèi)容編寫成獨(dú)立的程序段,并將它們配上相應(yīng)的條件編譯命令。因環(huán)境不同等原因,只要設(shè)定相應(yīng)條件,就能組裝出適應(yīng)環(huán)境要求的新程序。
條件編譯命令主要有三種相似的形式。
(1) #if 表達(dá)式轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
程序段1
# else
程序段2
# endif
其中表達(dá)式為常量表達(dá)式,其意義是當(dāng)指定的表達(dá)式值為非零時(shí),程序段1參與編譯,程序段2不參與編譯;否則,反之。
這種形式的條件編譯命令使預(yù)處理程序能根據(jù)給定的條件確定哪個(gè)程序段參與編譯,哪個(gè)程序段不參與編譯。
在上述一般形式中,當(dāng)程序段2不出現(xiàn)時(shí),也可簡寫為
#if 表達(dá)式
程序段
# endif
條件編譯與if語句有重要區(qū)別:條件編譯是在預(yù)處理時(shí)判定的,不產(chǎn)生判定代碼,其中一個(gè)不滿足條件的程序段不參與編譯,不會(huì)產(chǎn)生代碼;且語句是在運(yùn)行時(shí)判定的,且編譯產(chǎn)生判
定代碼和兩個(gè)分支程序段的代碼。因此,條件編譯可減少目標(biāo)程序長度,能提高程序執(zhí)行速度。但條件編譯只能測試常值或常量表達(dá)式,而且語句能對(duì)表達(dá)式作動(dòng)態(tài)測試。
條件編譯預(yù)處理命令也可呈嵌套結(jié)構(gòu)。特別是為了便于描述# else后的程序段又是條件編譯情況,引人須處理命令符# elif.它的意思就是# else #if.所以條件編譯須處理命令更一般的形式為
# if 表達(dá)式 1轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
程序段1
# elif 表達(dá)式 2
程序段2
# elif 表達(dá)式 n
程序段n
# else
程序段 n+l
# endif
(2) # ifdef 標(biāo)識(shí)符
程序段1
# else
程序段2
# endif
其中標(biāo)識(shí)符是一個(gè)宏名,上述意義是當(dāng)宏名已被定義,則程序段里參與編譯,程序段2不參與編譯;否則,反之。這里的程序段可以是任何C代碼行,也可以包含預(yù)處理命令行。其中的標(biāo)識(shí)符只要求已定義與否,與標(biāo)識(shí)符被定義成什么是無關(guān)的。如標(biāo)識(shí)符只用于這個(gè)目的,常用以下形式的宏定義來定義這類標(biāo)識(shí)符:
# define 標(biāo)識(shí)符轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
即標(biāo)識(shí)符之后為空,直接以換行結(jié)束該宏定義命令。
在上述一般形式中,如果程序段2為空,則可簡寫成如下一般形式:
# ifdef 標(biāo)識(shí)符
程序段
# endif
條件編譯主要作用是能提高程序的通用性,應(yīng)用于不同的計(jì)算機(jī)系統(tǒng)編譯不同的源程序段。條件編譯另一種應(yīng)用是在程序中插入調(diào)試狀態(tài)下輸出中間結(jié)果的代碼。如:
# ifdef DEBUG
printf(“a=%d, b=%d \n”, a, b);
# endif
程序在調(diào)試狀態(tài)下與包含宏定義命令
# define BEBUG
的頭文件一起編譯;在要獲得最終目標(biāo)程序時(shí),不與包含該宏定義命令的頭文件一起編譯。這樣,在調(diào)試通過后,不必再修改程序,已獲得了正確的最終程序。為了日后程序維護(hù),將調(diào)試時(shí)使用的程序代碼留在源程序中是專業(yè)程序員習(xí)慣采用的方法。因?yàn)檫@些代碼的存在不影響最終目標(biāo)碼,但有助于日后修改程序時(shí)的調(diào)試需要。
(3) # ifndef 標(biāo)識(shí)符
程序段1
# else
程序段2
# endif
這種條件編譯形式與前面介紹的形式的唯一差異是第一行的ifdef改為ifndef.其意義是當(dāng)標(biāo)識(shí)符末被定義時(shí),程序段1參與編譯,程序段2不參與編譯;否則,反之。在上述形式中,當(dāng)程序段2不出現(xiàn)時(shí),可簡寫成:
# infdef 標(biāo)識(shí)符
程序段
# endif轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
9.4 帶參數(shù)的主函數(shù)
在操作系統(tǒng)下執(zhí)行某個(gè)C程序,是環(huán)境對(duì)C程序的啟動(dòng),可以看作是對(duì)該程序的main()函數(shù)的調(diào)用。main()函數(shù)執(zhí)行結(jié)束后,控制返回環(huán)境。為能從環(huán)境向C程序傳遞信息,啟動(dòng)C程序的命令行可帶有任選的參數(shù)。命令行的一般形式為
程序名 參數(shù)1 參數(shù)2……參數(shù)n
其中程序名和各參數(shù)之間用空白符分隔。
為能讓main()函數(shù)讀取命令行中的參數(shù),環(huán)境將多個(gè)參數(shù)以兩個(gè)參數(shù)形式傳遞給main()函數(shù)、其中第一個(gè)參數(shù)(習(xí)慣記作argc) 表示命令行中參數(shù)的個(gè)數(shù)(包括程序名);第二個(gè)參數(shù)(習(xí)慣記作argv)是一個(gè)字符指針數(shù)組。其中argv[0] 指向程序名字符串的第一個(gè)字符,argv[1]指向參數(shù)1字符串的第一個(gè)字符,…,argv[argc-1] 指向最后一個(gè)參數(shù)字符串的第一個(gè)字符。如果利因山等于1,則表示程序名后面沒有參數(shù)。下面的例子用于說明main()函數(shù)對(duì)參數(shù)argc
與argv的引用方法。
「例9.l」 回打啟動(dòng)程序時(shí)的命令行各參數(shù)。
# include
void main(int argc, char *argv[] /* 或char **argv; */)
{ int k;
for( k=l; k
printf(“%c”,argv[k],k
printf(“\n\n”);
}
如上述程序的執(zhí)行程序名為echopro.exe,執(zhí)行該程序的命令行為:
echopro Hello world!
則程序?qū)⑤敵?font color="#f1f6fc">轉(zhuǎn)自環(huán) 球 網(wǎng) 校edu24ol.com
Hello world!
在以上命令行中,根據(jù)約定,main()函數(shù)的參數(shù)argc的值為3;argv[0],argv[1],argv[2]分別指向字符串“echopro”、“Hello”、“world!”的第一個(gè)字符。在程序的printf()函數(shù)調(diào)用中,字符輸出格式%c輸出一個(gè)字符,若是已輸出了命令行最后一個(gè)參數(shù),該格式將輸出一個(gè)換行符,若是輸出其它參數(shù),則輸出一個(gè)空白符。
因函數(shù)的數(shù)組參數(shù)是指向數(shù)組首元素的指針變量,所以在主函數(shù)main()中可對(duì)argv施行增量運(yùn)算。例如,在argv[0]指針指向程序名字符串的第一個(gè)字符情況下,對(duì)argv施增量運(yùn)算++argv后,argv[0](或*argv)就指向參數(shù)1的第一個(gè)字符c利用argv的這一性質(zhì),可改寫上述程序?yàn)橐韵滦问剑?/p>
# include
void main(int argc,char **argv)
{ while(——argc>0)
printf(“%s%c”,*++argv,argc>1? '':'\n');
}
這里,++argv使指針argv先加1,讓它一開始就指向參數(shù)1;逐次增回,使它遍歷指向各參數(shù)。又利用函數(shù)printf()的第一個(gè)格式參數(shù)是字符串表達(dá)式,上述程序?qū)rintf()的調(diào)用可改寫成:
printf((argc> l) ? “%s”:“%s\n”,* ++argv);
「例9.2」 假定啟動(dòng)程序時(shí)給出的命令行參數(shù)是一串整數(shù),程序?qū)⑷空麛?shù)求和后輸出。
# include
# include
void main( int argc,char **argv)
{ int k,s;
for(s=0, k=l; k
s+=atoi(*++agv); /* 從數(shù)字字符串譯出整數(shù) */
printf( “\t%d\n”, s);
}
·2010年上半年自學(xué)考試報(bào)名時(shí)間匯總
·環(huán)球網(wǎng)校2010年自學(xué)考試輔導(dǎo)招生簡章
更多信息請(qǐng)?jiān)L問:自學(xué)考試頻道 自學(xué)考試論壇 自學(xué)考試博客圈
最新資訊
- 考前必背!自學(xué)考試《中國近現(xiàn)代史綱要》論述題高頻考點(diǎn)2024-10-19
- 自考報(bào)考策略:科學(xué)搭配科目,加速畢業(yè)進(jìn)程2024-07-20
- 2025年考研考生五一假期,英語科目應(yīng)該如何復(fù)習(xí)?2024-05-03
- 備考指南!2024年4月自學(xué)考試考前要做哪些準(zhǔn)備?2024-03-31
- 考前備考沖刺!自考如何一次就過?2024-03-30
- 考點(diǎn)匯總:《中國近現(xiàn)代史綱要》論述題2024-03-25
- 備考資料:《中國近現(xiàn)代史綱要》簡答題考點(diǎn)匯總2024-03-25
- 自考可以從哪些維度進(jìn)行備考?2024-02-17
- @自考生,這里有備考技巧2024-02-17
- 自學(xué)考試備考復(fù)習(xí)方法!建議收藏2024-02-16