編譯預處理

2021-06-20 21:22:21 字數 2886 閱讀 3353

所謂編譯預處理,就是在c源程式的編譯之前,由編譯預處理程式對這些編譯預處理命令進行處理的過程。最常見的就是常量的替換。編譯預處理按功能可以分為巨集定義,檔案包含和條件編譯三類。編譯預處理命令以#開頭,下面進行詳細說明:

一. 巨集定義與符號常量

1. 

無參巨集定義

#define 

識別符號

字串

(1)巨集名一般用大寫字母表示,以示與變數區別。

(2)巨集定義不是c語句,所以不能在行尾加分號。

(3)對於巨集定義不做拼寫檢查,直接無腦替換

(4)巨集定義命令#define出現在函式的外部,巨集名的有效範圍是:從定義命令之後, 到本檔案結束。

(5)在進行巨集定義時,可以引用已定義的巨集名 。

(6)沒有字串的巨集成為空符號常量,在編譯處理時將被刪掉。

例子:1.#define  pi  3.14

2.#define width 

80 #define length  (width+40)

3.  #define  reg

2. 

有參巨集定義

#define 

巨集名(形參表

字串

#define 

巨集名(參表

字串

巨集展開:用巨集呼叫提供的實參字串,直接置換巨集定義命令列中、相應形參字串,非形參字元保持不變。

(1)定義有參巨集時,巨集名與「(」之間不能留有空格。

(2)有參巨集的展開,只是將實參作為字串,簡單地置換形參字串,而不做任何語法檢查。

(3)雖然有參巨集與有參函式確實有相似之處,但不同之處更多,主要有以下幾個方面:

1)呼叫有參函式時,是先求出實參的值,然後再複製乙份給形參。而展開有參巨集時,只是將實參簡單地置換形參。

2)在有參函式中,形參是有型別的,所以要求實參的型別與其一致;而在有參巨集中,形參是沒有型別資訊的, 因此可利用有參巨集的這一特性,實現通用函式功能。

3)使用有參函式,無論呼叫多少次,都不會使目標程式變長,但每次呼叫都要占用系統時間進行呼叫現場保護和現場恢復;而使用有參巨集,由於巨集展開是在編譯時進行的,所以不佔執行時間,但是每引用1次,都會使目標程式增大1次。 

例子:1.#define max(a,b) (a)>(b)?(a):(b)//判斷較大值

2.#define abs(a) 

((a>=0)?a:-a)//求絕對值

3.#define isodd(a) ((a%2==1)?1:0)//判斷是否是奇數

二. 檔案包含 

1. 檔案包含的概念: 檔案包含是指,乙個原始檔可以將另乙個原始檔的全部內容包含進來

命令格式:

include 

包含檔名

include 

<包含檔名>

這兩種格式的區別僅在於:

(1)使用雙引號:系統首先到當前目錄下查詢被包含檔案,如果沒找到,再到系統指定的「包含檔案目錄」(由使用者在配置環境時設定)去查詢。

(2)使用尖括號:直接到系統指定的「包含檔案目錄」去查詢。一般地說,使用雙引號比較保險。

3.檔案包含的優點:

乙個大程式,通常分為多個模組,並由多個程式設計師分別程式設計。有了檔案包含處理功能,就可以將多個模組共用的資料(如符號常量和資料結構)或函式,集中到乙個單獨的檔案中。這樣,凡是要使用其中資料或呼叫其中函式的程式設計師,只要使用檔案包含處理功能,將所需檔案包含進來即可,不必再重複定義它們,從而減少重複勞動。

4.說明

(1)編譯預處理時,預處理程式將查詢指定的被包含檔案,並將其複製到#include命令出現的位置上。

(2)常用在檔案頭部的被包含檔案,稱為「標題檔案」或「頭部檔案」,常以「h」(head)作為字尾,簡稱標頭檔案。在標頭檔案中,除可包含巨集定義外,還可包含外部變數定義、結構型別定義等。

(3)一條包含命令,只能指定乙個被包含檔案。如果要包含n個檔案,則要用n條包含命令。

(4)檔案包含可以巢狀,即被包含檔案中又包含另乙個檔案。

三.條件編譯

1.  #ifdef ~ #endif和#ifndef ~ #endif命令

(1)一般格式

#ifdef 

識別符號 程式段1;

[#else

程式段2;] 

#endif

(2)功能:當「識別符號」已經被#define命令定義過,則編譯程式段1,否則編譯程式段2。

例子:

#define  tag  1

...

#ifdef  tag

...

#endif

說明:1)在不同的系統中,乙個int 型資料占用的記憶體位元組數可能是不同的。 

2)利用條件編譯,還可使同一源程式即適合於除錯(進行程式跟蹤、列印較多的狀態或錯誤資訊),又適合高效執行要求。

(3)關於#ifndef ~ #endif命令

格式與#ifdef ~ #endif命令一樣,功能正好與之相反。

2. 

#if ~ #endif

(1)一般格式

#if 

常量表示式

程式段1;

[#else

程式段2;]

#endif

(2)功能:當表示式為非0(「邏輯真」)時,編譯程式段1,否則編譯程式段2。

例子:輸入乙個口令,根據需要是否編譯除錯**。

#define 

debug 

0 main()

編譯預處理

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.列舉只可以表示整型,巨集...

編譯預處理

我們知道在編譯過程中的預處理階段會進行標頭檔案展開,巨集替換以及條件編譯。1.標頭檔案展開 首先是標頭檔案展開,標頭檔案的前面都有 符號,其實是理指令。理指令是以 號開頭的 行。號必須是該行除了任何空白字元外的第乙個字元。後是指令關鍵字,在關鍵字和 號 之間允許存在任意個數的空白字元。整行語句構成了...