《第08章 編譯預(yù)處理》由會(huì)員分享,可在線閱讀,更多相關(guān)《第08章 編譯預(yù)處理(16頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、第第8章章 編譯預(yù)處理編譯預(yù)處理所謂編譯預(yù)處理是指,在對(duì)源程序進(jìn)行編譯之前,先對(duì)源程序中的編譯預(yù)處理命令進(jìn)行處理;然后再將處理的結(jié)果,和源程序一起進(jìn)行編譯,以得到目標(biāo)代碼。 8.1 宏定義與符號(hào)常量宏定義與符號(hào)常量8.2 文件包含文件包含8.3 條件編譯條件編譯 Return8.1 宏定義與符號(hào)常量宏定義與符號(hào)常量在語(yǔ)言中,“宏”分為無(wú)參數(shù)的宏(簡(jiǎn)稱無(wú)參宏)和有參數(shù)的宏(簡(jiǎn)稱有參宏)兩種。8.1.1 無(wú)參宏定義無(wú)參宏定義8.1.2 符號(hào)常量符號(hào)常量8.1.3 有參宏定義有參宏定義Return8.1.1 無(wú)參宏定義無(wú)參宏定義 1無(wú)參宏定義的一般格式無(wú)參宏定義的一般格式 #define 標(biāo)識(shí)符標(biāo)識(shí)
2、符 語(yǔ)言符號(hào)字符串語(yǔ)言符號(hào)字符串其中:“define”為宏定義命令;“標(biāo)識(shí)符”為所定義的宏名,通常用大寫(xiě)字母表示,以便于與變量區(qū)別;“語(yǔ)言符號(hào)字符串”可以是常數(shù)、表達(dá)式、格式串等。2使用宏定義的優(yōu)點(diǎn)使用宏定義的優(yōu)點(diǎn)(1)可提高源程序的可維護(hù)性(2)可提高源程序的可移植性 (3)減少源程序中重復(fù)書(shū)寫(xiě)字符串的工作量案例案例8.1 輸入圓的半徑,求圓的周長(zhǎng)、面積和球的體積。要求使用無(wú)參宏定義圓周率。/*案例代碼文件名:AL8_1.C*/*程序功能:輸入圓的半徑,求圓的周長(zhǎng)、面積和球的體積。 */#define PI 3.1415926 /*PI是宏名,3.1415926用來(lái)替換宏名的常數(shù)*/main
3、() float radius,length,area,volume; printf(Input a radius: ); scanf(%f,&radius); length=2*PI*radius; /*引用無(wú)參宏求周長(zhǎng)*/ area=PI*radius*radius; /*引用無(wú)參宏求面積*/ volume=PI*radius*radius*radius*3/4; /*引用無(wú)參宏求體積*/ printf(length=%.2f,area=%.2f,volume=%.2fn, length, area, volume); 程序演示3說(shuō)明說(shuō)明(1)宏名一般用大寫(xiě)字母表示,以示與變量區(qū)別。但這并
4、非是規(guī)定。 (2)宏定義不是語(yǔ)句,所以不能在行尾加分號(hào)。否則,宏展開(kāi)時(shí),會(huì)將分號(hào)作為字符串的1個(gè)字符,用于替換宏名。(3)在宏展開(kāi)時(shí),預(yù)處理程序僅以按宏定義簡(jiǎn)單替換宏名,而不作任何檢查。如果有錯(cuò)誤,只能由編譯程序在編譯宏展開(kāi)后的源程序時(shí)發(fā)現(xiàn)。(4)宏定義命令#define出現(xiàn)在函數(shù)的外部,宏名的有效范圍是:從定義命令之后, 到本文件結(jié)束。通常,宏定義命令放在文件開(kāi)頭處。 (5)在進(jìn)行宏定義時(shí),可以引用已定義的宏名 。(6)對(duì)雙引號(hào)括起來(lái)的字符串內(nèi)的字符,即使與宏名同名,也不進(jìn)行宏展開(kāi)。 Return8.1.2 符號(hào)常量符號(hào)常量在定義無(wú)參宏時(shí),如果“語(yǔ)言符號(hào)字符串”是一個(gè)常量,則相應(yīng)的“宏名”就
5、是一個(gè)符號(hào)常量。恰當(dāng)命名的符號(hào)常量,除具有宏定義的上述優(yōu)點(diǎn)外,還能表達(dá)出它所代表常量的實(shí)際含義,從而增強(qiáng)程序的可讀性。#define EOF -1 /*文件尾*/#define NULL 0/*空指針*/#define MIN 1 /*極小值*/#define MAX 31 /*極大值*/#define STEP 2 /*步長(zhǎng)*/ Return8.1.3 有參宏定義有參宏定義1帶參宏定義的一般格式#define 宏名宏名(形參表形參表) 語(yǔ)言符號(hào)字符串語(yǔ)言符號(hào)字符串2帶參宏的調(diào)用和宏展開(kāi)(1)調(diào)用格式:宏名宏名(實(shí)參表實(shí)參表)(2)宏展開(kāi):用宏調(diào)用提供的實(shí)參字符串,直接置換宏定義命令行中、相應(yīng)
6、形參字符串,非形參字符保持不變。3說(shuō)明(1)定義有參宏時(shí),宏名與左圓括號(hào)之間不能留有空格。否則,編譯系統(tǒng)將空格以后的所有字符均作為替代字符串,而將該宏視為無(wú)參宏。(2)有參宏的展開(kāi),只是將實(shí)參作為字符串,簡(jiǎn)單地置換形參字符串,而不做任何語(yǔ)法檢查。在定義有參宏時(shí),在所有形參外和整個(gè)字符串外,均加一對(duì)圓括號(hào)。 (3)雖然有參宏與有參函數(shù)確實(shí)有相似之處,但不同之處更多,主要有以下幾個(gè)方面:1)調(diào)用有參函數(shù)時(shí),是先求出實(shí)參的值,然后再?gòu)?fù)制一份給形參。而展開(kāi)有參宏時(shí),只是將實(shí)參簡(jiǎn)單地置換形參。2)在有參函數(shù)中,形參是有類(lèi)型的,所以要求實(shí)參的類(lèi)型與其一致;而在有參宏中,形參是沒(méi)有類(lèi)型信息的,因此用于置換的
7、實(shí)參,什么類(lèi)型都可以。有時(shí),可利用有參宏的這一特性,實(shí)現(xiàn)通用函數(shù)功能。3)使用有參函數(shù),無(wú)論調(diào)用多少次,都不會(huì)使目標(biāo)程序變長(zhǎng),但每次調(diào)用都要占用系統(tǒng)時(shí)間進(jìn)行調(diào)用現(xiàn)場(chǎng)保護(hù)和現(xiàn)場(chǎng)恢復(fù);而使用有參宏,由于宏展開(kāi)是在編譯時(shí)進(jìn)行的,所以不占運(yùn)行時(shí)間,但是每引用1次,都會(huì)使目標(biāo)程序增大1次。 Return8.2 文件包含文件包含1文件包含的概念文件包含是指,一個(gè)源文件可以將另一個(gè)源文件的全部?jī)?nèi)容包含進(jìn)來(lái)。2文件包含處理命令的格式include “包含文件名包含文件名” 或 include 兩種格式的區(qū)別僅在于:(1)使用雙引號(hào):系統(tǒng)首先到當(dāng)前目錄下查找被包含文件,如果沒(méi)找到,再到系統(tǒng)指定的“包含文件目錄”
8、(由用戶在配置環(huán)境時(shí)設(shè)置)去查找。(2)使用尖括號(hào):直接到系統(tǒng)指定的“包含文件目錄”去查找。一般地說(shuō),使用雙引號(hào)比較保險(xiǎn)。 3文件包含的優(yōu)點(diǎn)一個(gè)大程序,通常分為多個(gè)模塊,并由多個(gè)程序員分別編程。有了文件包含處理功能,就可以將多個(gè)模塊共用的數(shù)據(jù)(如符號(hào)常量和數(shù)據(jù)結(jié)構(gòu))或函數(shù),集中到一個(gè)單獨(dú)的文件中。這樣,凡是要使用其中數(shù)據(jù)或調(diào)用其中函數(shù)的程序員,只要使用文件包含處理功能,將所需文件包含進(jìn)來(lái)即可,不必再重復(fù)定義它們,從而減少重復(fù)勞動(dòng)。4說(shuō)明(1)編譯預(yù)處理時(shí),預(yù)處理程序?qū)⒉檎抑付ǖ谋话募⑵鋸?fù)制到#include命令出現(xiàn)的位置上。 (2)常用在文件頭部的被包含文件,稱為“標(biāo)題文件”或“頭部
9、文件”,常以“h”(head)作為后綴,簡(jiǎn)稱頭文件。在頭文件中,除可包含宏定義外,還可包含外部變量定義、結(jié)構(gòu)類(lèi)型定義等。(3)一條包含命令,只能指定一個(gè)被包含文件。如果要包含n個(gè)文件,則要用n條包含命令。(4)文件包含可以嵌套,即被包含文件中又包含另一個(gè)文件。 Return8.3 條件編譯 條件編譯可有效地提高程序的可移植性,并廣泛地應(yīng)用在商業(yè)軟件中,為一個(gè)程序提供各種不同的版本。 8.3.1 #ifdef #endif和和#ifndef #endif命令命令 8.3.2 #if #endifReturn8.3.1 #ifdef #endif和#ifndef #endif命令1一般格式一般格式
10、 ifdef 標(biāo)識(shí)符 程序段1; else 程序段2; endif2功能功能:當(dāng)“標(biāo)識(shí)符”已經(jīng)被#define命令定義過(guò),則編譯程序段1,否則編譯程序段2。(1)在不同的系統(tǒng)中,一個(gè)int 型數(shù)據(jù)占用的內(nèi)存字節(jié)數(shù)可能是不同的。 (2)利用條件編譯,還可使同一源程序即適合于調(diào)試(進(jìn)行程序跟蹤、打印較多的狀態(tài)或錯(cuò)誤信息),又適合高效執(zhí)行要求。 3關(guān)于關(guān)于#ifndef #endif命令命令格式與#ifdef #endif命令一樣,功能正好與之相反。 Return8.3.2 #if #endif1一般格式一般格式 if 常量表達(dá)式 程序段1; else 程序段2; endif2功能功能:當(dāng)表達(dá)式為非0(“邏輯真”)時(shí),編譯程序段1,否則編譯程序段2。 案例案例8.2 輸入一個(gè)口令,根據(jù)需要設(shè)置條件編譯,使之能將口令原碼輸出,或僅輸出若干星號(hào)“*”。 /*案例代碼文件名:AL8_2.C*/#define PASSWORD 0 /*預(yù)置為輸出星號(hào)*/main() /*條件編譯*/ #if PASSWORD /*源碼輸出*/ #else /*輸出星號(hào)*/ #endif Return