編譯預處理

2021-07-24 20:12:39 字數 1506 閱讀 4746

我們知道在編譯過程中的預處理階段會進行標頭檔案展開,巨集替換以及條件編譯。

1.標頭檔案展開:

首先是標頭檔案展開,標頭檔案的前面都有#符號,其實是理指令。

理指令是以#號開頭的**行。#號必須是該行除了任何空白字元外的第乙個字元。#後是指令關鍵字,在關鍵字和#號

之間允許存在任意個數的空白字元。整行語句構成了一條預處

理指令,該指令將在編譯器進行編譯之前對源**做某

些轉換。下面是部分預處理指令:

#           空指令,無任何效果

#include    包含乙個源**檔案   

#define     定義巨集   

#undef      取消已定義的巨集

#if         如果給定條件為真,則編譯下面**

#ifdef      如果巨集已經定義,則編譯下面**

#ifndef     如果巨集沒有定義,則編譯下面**

#elif       如果前面的#if給定條件不為真,當前條件為真,則編譯下面**,其實就是else if的簡寫

#endif      結束乙個#if……#else條件編譯塊

#error      停止編譯並顯示錯誤資訊

2.巨集定義:

巨集定義了乙個代表特定內容的識別符號。預處理過程會把源**中出現的巨集識別符號替換成巨集定義時的值。巨集最常見的用

法是定義代表某個值的全域性符號。

巨集的第二種用 法是定義帶引數的巨集(巨集函式),這樣的巨集可以象函式一樣被呼叫,但它是在呼叫語句處展開巨集,並用

呼叫時的實際引數來代替定義中的形式引數。

像這樣#define max(a,b) a> b?a:b  就是定義了乙個巨集函式。

巨集函式與自定義函式相比:巨集函式可以省去分配和釋放棧幀,傳參,傳返回值等一系列工作,因此那些簡短並且被頻

繁呼叫的函式可以用函式式巨集定義來代替實現。

但是巨集函式發生在預處理階段,只進行盲目替換,不進行語法檢查,所以容易出錯,而且不能實現一些複雜的功能。

一些內建巨集定義:

__func__          顯示這行**所在函式的函式名

__line__         顯示行號

__time__         顯示當前時間

__date__        顯示當前日期

3.條件編譯:

條件編譯我們會經常看到這樣的一些指令如:#if  #endif   #else   #elif等等。

我們需要掌握#ifdef和#ifndef指令。

這二者主要用於防止標頭檔案重複包含帶來的重複定義。我們一般在.h標頭檔案前面加上這麼一段:

//標頭檔案防止重複包含

#ifndef funca_h

#define funca_h

//標頭檔案內容

#end if

這樣,如果a.h包含了funca.h,b.h包含了a.h、funca.h,重複包含,會出現一些type redefination之類的錯誤。

#if defined等價於#ifdef; #if !defined等價於#ifndef

編譯預處理

所謂編譯預處理,就是在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.列舉只可以表示整型,巨集...