預處理詳解

2021-08-10 17:34:09 字數 3024 閱讀 2253

預處理指令是以#號開頭的**行。#號必須是該行除了任何空白字元外的第乙個字元。#後是指令關鍵字,在關鍵字和#號之間允許存在任意個數的空白字元。整行語句構成了一條預處理指令,該指令將在編譯器進行編譯之前對源**做某些轉換。下面是部分預處理指令:

指令 用途

空指令,無任何效果

#include 

包含乙個源**檔案

#define 

定義巨集#undef 

取消已定義的巨集

#if 

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

#ifdef 

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

#ifndef 

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

#elif 

如果前面的#if給定條件不為真,當前條件為真,則編譯下面**,相當於#elseif

#endif 

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

#error 

停止編譯並顯示錯誤資訊

一、檔案包含

#include預處理指令的作用是在指令處展開被包含的檔案。包含可以是多重的,也就是說乙個被包含的檔案中還可以包含其他檔案。標準c編譯器至少支援八重巢狀包含。

預處理過程不檢查在轉換單元中是否已經包含了某個檔案並阻止對它的多次包含。這樣就可以在多次包含同乙個標頭檔案時,通過給定編譯時的條件來達到不同的效果。例如:

#define aaa

#i nclude "t.c"

#undef aaa

#i nclude "t.c"

為了避免那些只能包含一次的標頭檔案被多次包含,可以在標頭檔案中用編譯時條件來進行控制。例如:

#ifndef my_h

#define my_h

……#endif

在程式中包含標頭檔案有兩種格式:

#i nclude

#i nclude "my.h"

第一種方法是用尖括號把頭檔案括起來。這種格式告訴預處理程式在編譯器自帶的或外部庫的標頭檔案中搜尋被包含的標頭檔案。第二種方法是用雙引號把頭檔案括起來。這種格式告訴預處理程式在當前被編譯的應用程式的源**檔案中搜尋被包含的標頭檔案,如果找不到,再搜尋編譯器自帶的標頭檔案。

二、巨集

巨集定義了乙個代表特定內容的識別符號。預處理過程會把源**中出現的巨集識別符號替換成巨集定義時的值。巨集最常見的用法是定義代表某個值的全域性符號。巨集的第二種用法是定義帶引數的巨集,這樣的巨集可以象函式一樣被呼叫,但它是在呼叫語句處展開巨集,並用呼叫時的實際引數來代替定義中的形式引數。

1.#define指令

#define預處理指令是用來定義巨集的。該指令最簡單的格式是:首先宣告乙個識別符號,然後給出這個識別符號代表的**。在後面的源**中,就用這些**來替代該識別符號。

巨集表示的值可以是乙個常量表示式,其中允許包括前面已經定義的巨集識別符號。例如:

#define one 1

#define two 2

#define three (one+two)

注意上面的巨集定義使用了括號。儘管它們並不是必須的。但出於謹慎考慮,還是應該加上括號的。

3.#運算子

出現在巨集定義中的#運算子把跟在其後的引數轉換成乙個字串。有時把這種用法的#稱為字串化運算子。例如:

#define paste(n) "adhfkj"#n

main()

巨集定義中的#運算子告訴預處理程式,把源**中任何傳遞給該巨集的引數轉換成乙個字串。所以輸出應該是adhfkj15。

4.##運算子

##運算子用於把引數連線到一起。預處理程式把出現在##兩側的引數合併成乙個符號。看下面的例子:

#define num(a,b,c) a##b##c

#define str(a,b,c) a##b##c

main()

最後程式的輸出為:

123aabbcc

三、條件編譯指令

條件編譯指令將決定那些**被編譯,而哪些是不被編譯的。可以根據表示式的值或者某個特定的巨集是否被定義來確定編譯條件。

1.#if指令

#if指令檢測跟在其後的巨集或表示式是否為真。如果表示式為真,則編譯後面的**,知道出現#else、#elif或#endif為止;否則就不編譯。

2.#endif指令

#endif用於終止#if預處理指令。

#define debug 0

main()

由於程式定義debug巨集代表0,所以#if條件為假,不編譯後面的**直到#endif,所以程式直接輸出running。

如果去掉#define語句,效果是一樣的。

3.#ifdef和#ifndef

#define debug

main()

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

4.#else指令

#else指令用於某個#if指令之後,當前面的#if指令的條件不為真時,就編譯#else後面的**。#endif指令將中指上面的條件塊。

#define debug

main()

5.#elif指令

#elif預處理指令綜合了#else和#if指令的作用。

#define two

main()

程式很好理解,最後輸出結果是2。

6.其他一些標準指令

#error指令將使編譯器顯示一條錯誤資訊,然後停止編譯。

#line指令可以改變編譯器用來指出警告和錯誤資訊的檔案號和行號。

#pragma指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告資訊。

pragma預處理詳解

在所有的預處理指令中,pragma 指令可能是最複雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。pragma指令對每個編譯器給出了乙個方法,在保持與c和c 語言完全相容的情況下,給出主機或作業系統專有的特徵。依據定義,編譯指示是機器或作業系統專有的,且對於每個編譯器都是不同的...

pragma 預處理指令詳解

pragma 預處理指令詳解 在所有的預處理指令中,pragma 指令可能是最複雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。pragma指令對每個編譯器給出了乙個方法,在保持與c和c 語言完全相容的情況下,給出主機或作業系統專有的特徵。依據定義,編譯指示是機器或作業系統專有...

pragma 預處理指令詳解

7 pragma comment 該指令將乙個注釋記錄放入乙個物件檔案或可執行檔案中。常用的lib關鍵字,可以幫我們連入乙個庫檔案。每個編譯程式可以用 pragma指令啟用或終止該編譯程式支援的一些編譯功能。例如,對迴圈優化功能 pragma loop opt on 啟用 pragma loop o...