9 10 編譯預處理

2021-04-14 02:34:22 字數 2802 閱讀 6797

9.10 編譯預處理

編譯預處理也是c語言區別其他高階語言的特點,是指在系統對源程式進行編譯之前,對程式中某些特殊的命令列的處理,預處理程式將根據源**中的預處理命令修改程式,使用預處理功能,可以改善程式的設計環境,提高程式的通用性、可讀性、可修改性、可除錯性、可移植性和方便性,易於模組化。

其處理過程如圖9-11所示。

預處理命令有以下幾個特點:

(1)預處理命令是一種特殊的命令,為了區別一般的語句,必須以#開頭,結尾不加分號。

(2)預處理命令可以放在程式中的任何位置,其有效範圍是從定義開始到檔案結束。

c語言中的預處理命令有巨集定義、檔案包含和條件編譯三類。

預處理命令有以下幾個特點:

(1)預處理命令是一種特殊的命令,為了區別一般的語句,必須以#開頭,結尾不加分號。

(2)預處理命令可以放在程式中的任何位置,其有效範圍是從定義開始到檔案結束。

c語言中的預處理命令有巨集定義、檔案包含和條件編譯三類。

9.10.1 巨集定義

巨集是提供了一種機制,可以用來替換源程式中的字串。從本質上說,就是替換,用一串字串替換程式中指定的識別符號。因此巨集定義也叫巨集替換,巨集替換有兩類:簡單的字元替換和帶引數的巨集替換。

1、字元替換

(1)格式:

#define 識別符號 字串

其中,識別符號稱為巨集名,字串稱為巨集替換體。

(2)功能:編譯之前,預處理程式將程式中該巨集定義之後出現的所有識別符號(巨集名)用指定的字串進行替換。在源程式通過編譯之前,c的編譯程式先呼叫c預處理程式對巨集定義進行檢查,每發現乙個識別符號,就用相應的字串替換,只有在完成了這個過程之後,才將源程式交給編譯系統。

例9-31:預處理。

#define n 10

main( )

編譯該程式之前,預處理程式首先將所有出現的n用10替換。這個過程叫做巨集展開。

(3)使用巨集應當注意的是

①巨集定義僅僅是符號替換,不是賦值語句,因此不做語法檢查。

②為了區別程式中其他的識別符號,巨集名的定義通常用大寫字母。

③雙引號中出現的巨集名不替換。

例如:#define pi 3.14159

printf ("pi=%f", pi);

結果為:pi=3.14159

雙引號中的pi不進行替換。

④如果提前結束巨集名的使用,程式中可以使用#undefine 。

⑤使用巨集定義可以巢狀,即後定義的巨集中可以使用先定義的巨集。

使用巨集可以有以下好處:

(1)在輸入源程式,可以節省許多操作。

(2)巨集經定義之後,可以使用多次,因此使用巨集可以增強程式的易讀性和可靠性。

(3)使用巨集系統不需額外的開銷,因為巨集所代表的**只在巨集出現的地方展開,因此並不會引起程式的跳轉。

2、帶引數的巨集

進行巨集替換時,可以像使用函式一樣,通過實參與形參傳遞資料,增加程式的靈活性。

(1)格式:

#define 識別符號(形參表) 形參表示式

例:#define s(a,b) (a>b)?(a):(b)

(2)功能:預處理程式將程式中出現的所有帶實參的巨集名,展開成由實參組成的表示式。

例9-32:帶引數的巨集替換。

#define s(a,b) (a>b)? (a):(b) /* 定義帶引數的巨集名s */

main( )

(3)說明:

① 巨集名與括號之間不可以有空格。

② 有些引數表示式必須加括號,否則,在實參表示式替換時,會出現錯誤

例:#define s(x) x*x

在程式中,a的值為5,b的值為8,c=s(a+b),替換後的結果為:

c=a+b*a+b

代入a和b的值之後,c=5+8*5+8,值是53,並不是希望的:

c=(a+b)*(a+b)

帶引數的巨集與函式類似,都有形參與實參,有時功能兩者效果是相同的,但二者是不相同的。其主要區別有:

① 函式的形參與實參要求型別一致,而巨集替換不要求型別。

② 函式只有乙個返回值,巨集替換有可能有多個結果。

③ 函式影響執行時間,巨集替換影響編譯時間。

④ 使用巨集有可能給程式帶來意想不到的***。

例9-33:求1到10平方之和。

方法一:使用函式

main( )

fun ( int k )

結果:1,4,9,……,100

方法二:使用巨集

#define fun(a) a*a

main( )

{ int k=1;

while ( k<=10 )

printf ( "%d", fun(k++) );

} 分析:預處理程式將程式中 帶實參的fun替換成(k++)*(k++),由於c語言中,實參的求值順序是從右向左,因此程式執行結果為:

第一次迴圈: (k++)*(k++) 為 2*1

第二次迴圈: (k++)*(k++) 為 4*3

第三次迴圈: (k++)*(k++) 為 6*5

第四次迴圈: (k++)*(k++) 為 8*7

第五次迴圈: (k++)*(k++) 為 10*9

程式執行過程共迴圈5次。

應當盡量避免用自增變數做巨集替換的實參。類似的還有:

#define sum(x) x*x*x

程式中:y=sum(++x);替換的結果即:

y=((++x)*(++x)*(++x))

本文**

編譯預處理

所謂編譯預處理,就是在c源程式的編譯之前,由編譯預處理程式對這些編譯預處理命令進行處理的過程。最常見的就是常量的替換。編譯預處理按功能可以分為巨集定義,檔案包含和條件編譯三類。編譯預處理命令以 開頭,下面進行詳細說明 一.巨集定義與符號常量 1.無參巨集定義 define 識別符號 字串 1 巨集名...

編譯預處理

1.巨集定義指令 1 定義變數與命令 避免幻數 在巨集定義命名時,盡量能清楚的表明功能,大寫 不能以 開頭易與內建巨集衝突 2 定義巨集函式 define max a,b a b a b int num max 6,5 6 5 6 5 用編譯時間換記憶體空間的是巨集函式 用記憶體空間換執行空間的是內...

編譯預處理

1 定義常量與命令 避免幻數 定義巨集時,避免以 開頭,以防與內建巨集定義衝突。巨集和列舉的區別 a.列舉常量是實體常量中的一種,但巨集不是實體 b.列舉常量屬於常量,但巨集不是常量 c.列舉常量具有型別,但巨集沒有型別。列舉型別主要用於限制性輸入,巨集只是預處理替換符 d.列舉只可以表示整型,巨集...