C語言的預編譯

2021-05-24 12:54:51 字數 3506 閱讀 8881

technorati 標籤:

c, 預編譯,

巨集, 檔案替換,

條件編譯

由「源**」到「可執行檔案」的過程包括四個步驟:預編譯編譯彙編鏈結。所以,首先就應該清楚的首要問題就是:預編譯只是對程式的文字起作用,換句話說就是,預編譯階段僅僅對源**的單詞進行變換,而不是對程式中的變數、函式等。

預編譯指令的基本知識不作詳細介紹,只稍作彙總,重點是後面的我能想到的 使用時的注意事項。

預編譯指令基本分類如下

類別指令

預定義符號

__file__、__line__、__date__、__time__、__stdc__

巨集#define

檔案包含

#include

條件編譯

#if、#elif、#else、#ifdef、#ifndef、#endif

還有一些指令,名稱和功能如下表:

指令功能

#空指令

#undef

移除乙個空定義

#error

停止編譯,並生成錯誤資訊

#line

修改__line__和__file__的值

#progma

允許編譯器提供額外功能

在定義巨集的時候,有兩個運算子

運算子功能

#將巨集引數轉換為字串

##將多個符號連線成乙個識別符號

1. 一般在巨集定義的結尾不加分號。

我們在使用的時候,要加上分號,像我們平時寫語句一樣。

2. 注意加括號。

在有引數的空定義中,如果含有數值運算,那麼就要在「巨集整體」和「巨集引數」兩端都要加上括號。

如:#define max(a, b) ((a)+(b)); 

3. 注意空格。

在有引數的巨集定義中,注意「巨集名稱」和「引數列表」之間不能有空格

如:#define max (a, b) ((a)+(b));  在"max」和」(a, b)」之間不能有空格。

4. 不要使用有***的引數區呼叫巨集。

常見的有***的引數有:a++,getchar()等。

如:巨集定義為#define max (a, b) ((a)+(b));  那麼使用max(i++, j++)呼叫該巨集,會造成 i 或 j 中的乙個值增加2,而不是我們期望的 1。

5. 可以使用編譯器選項 新增巨集 和 移除巨集。

我使用的是gcc,新增巨集的指令是」-d」,移除巨集的指令是」-u」。

6. 巨集引數替換的時候,不會替換字串中的字元。

即不會替換雙引號之間的字元,其他的都會被替換,包括單引號之間的。

7. 可以使用#將巨集引數的值轉化為字串。

直接使用#,是將巨集引數的名稱轉化為字串。利用下面的技巧(增加乙個過渡巨集),可以將「巨集引數的值」轉化為字串(當巨集引數有值時,這時的巨集引數常常也是乙個巨集)。

#include #include #define number ten   /* 巨集名稱為number,巨集的值為ten */

#define str(x) #x

#define xstr(x) str(x) /* 增加的乙個 過渡巨集 */

int main()

輸出結果為:

str(number) == number

xstr(number) == ten

8. 使用##運算子來實現識別符號連線。

不過,不建議使用操作符##來連線識別符號,因為這個容易是程式可讀性大大降低。

1. 要將標頭檔案的定義在保護條件中。

目的是為了防止重複包含標頭檔案。如果你檢視過gcc或者其他編譯器的源**,你一定對這個非常熟悉。

例如,你要編寫乙個標頭檔案,myheader.h,那麼你的標頭檔案的內容形式應該為:(定義乙個_myheader巨集)

#ifndef _myheader

#define _myheader 1

/* 中間是你的標頭檔案內容 */

#endif /* _myheader */

2. 注意windows系統和unix系統的路徑符號不同。

可以再#include中指定路徑來包含檔案,例如 #include 「../head.h」。但是注意,windows中使用反斜線」/」作為路徑分隔符,而unix系統使用的是斜線」/」

3. 可以使用 編譯器選項 來設定搜尋路徑。

我使用的gcc,使用的-idir選項,例如: -i"d:/dev-cpp/include"。

1. #ifdef等價於#if defined(),#ifndef等價於#if !defined()。

2. 在#if中可以使用邏輯操作符(&&、||、!)。在#ifdef 中是不可以使用的,這也是#if的優越點。

#include #include #define a 1

#define b 0

int main()

執行結果:

test logic operation in #if
3. sizeof(int)在預編譯階段是不會被求值的。

只要知道「預編譯階段」在真正的「編譯階段」之前,就很容易理解了。預編譯階段只是對組成源**中的字元進行作用,從某種意義上來說,它有時甚至不知道它的操作物件是什麼,它只是按照既定的規則執行替換。

sizeof(int),無論是sizeof的解析,還是型別的解析,都是在「編譯階段」才開始的,編譯階段知道它的操作物件是什麼。

下面的**是錯誤

#if sizeof(int) == 2

printf("precompile sizeof(int)");

#endif

把乙個預處理指令寫成多行的形式,要使用符號」/」,並且在該符號後面應緊跟換行符。而非預處理指令**行不需要使用該符號,直接換行即可。 原因:編譯階段會自動忽略空白符,而預編譯階段不會。

C語言的預編譯

預編譯指令基本分類如下 類別指令 預定義符號 file line date time stdc 巨集 define 檔案包含 include 條件編譯 if elif else ifdef ifndef endif 還有一些指令,名稱和功能如下表 指令功能 空指令 undef 移除乙個空定義 err...

C語言的預編譯

預處理功能主要包括巨集定義,檔案包含,條件編譯三部分。分別對應巨集定義命令,檔案包含命令,條件編譯命令三部分實現。預處理過程讀入源 檢查包含預處理指令的語句和巨集定義,並對源 進行響應的轉換。預處理過程還會刪除程式中的注釋和多餘的空白字元。預處理指令是以 號開頭的 行。號必須是該行除了任何空白字元外...

c語言中預編譯

預編譯又被稱為預處理,是做 文字的替換工作。處理 開頭的指令。就是為編譯做預備工作的準備。常見的預編譯指令有三種 1 include指令 該指令指示編輯器將 檔案的全部內容插入此處,如果使用 代表在系統指定目錄下搜尋檔案,使用 代表現在當前目錄下搜尋檔案,然後在系統預設目錄下搜尋。2 define指...