所謂編譯預處理,就是在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.標頭檔案展開 首先是標頭檔案展開,標頭檔案的前面都有 符號,其實是理指令。理指令是以 號開頭的 行。號必須是該行除了任何空白字元外的第乙個字元。後是指令關鍵字,在關鍵字和 號 之間允許存在任意個數的空白字元。整行語句構成了...