指令 用途
# 空指令,無任何效果
#include
包含乙個源**檔案
#define
定義巨集#undef
取消已定義的巨集
#if
如果給定條件為真,則編譯下面**
#ifdef
如果巨集已經定義,則編譯下面**
#ifndef
如果巨集沒有定義,則編譯下面**
#elif
如果前面的
#if給定條件不為真,當前條件為真,則編譯下面**
#endif
結束乙個
#if……#else
條件編譯塊
#error
停止編譯並顯示錯誤資訊
一、檔案包含
為了避免那些只能包含一次的標頭檔案被多次包含,可以在標頭檔案中用編譯時條件來進行控制。例如:
#ifndef my_h
#define my_h
…… #endif
二、巨集 1.#define
指令 #define
預處理指令是用來定義巨集的。該指令最簡單的格式是:首先神明乙個識別符號,然後給出這個識別符號代表的**。在後面的源**中,就用這些**來替代該識別符號。這種巨集把程式中要用到的一些全域性值提取出來,賦給一些記憶識別符號。
#define max_num 10
int array[max_num];
for(i=0;i
在這個例子中,對於閱讀該程式的人來說,符號
max_num
就有特定的含義,它代表的值給出了陣列所能容納的最大元素數目。程式中可以多次使用這個值。作為一種約定,習慣上總是全部用大寫字母來定義巨集,這樣易於把程式紅的巨集識別符號和一般變數識別符號區別開來。如果想要改變陣列的大小,只需要更改巨集定義並重新編譯程式即可。
巨集表示的值可以是乙個常量表示式,其中允許包括前面已經定義的巨集識別符號。例如:
#define one 1
#define two 2
#define three (one+two)
注意上面的巨集定義使用了括號。儘管它們並不是必須的。但出於謹慎考慮,還是應該加上括號的。例如:
six=three*two;
預處理過程把上面的一行**轉換成:
six=(one+two)*two;
如果沒有那個括號,就轉換成
six=one+two*two;
了。 巨集還可以代表乙個字串常量,例如:
2.帶引數的
#define
指令 帶引數的巨集和函式呼叫看起來有些相似。看乙個例子:
#define cube(x) (x)*(x)*(x)
可以時任何數字表示式甚至函式呼叫來代替引數
x。這裡再次提醒大家注意括號的使用。巨集展開後完全包含在一對括號中,而且引數也包含在括號中,這樣就保證了巨集和引數的完整性。看乙個用法:
int num=8+2;
volume=cube(num);
展開後為
(8+2)*(8+2)*(8+2);
如果沒有那些括號就變為
8+2*8+2*8+2
了。 下面的用法是不安全的:
volume=cube(num++);
如果cube
是乙個函式,上面的寫法是可以理解的。但是,因為
cube
是乙個巨集,所以會產生***。這裡的擦書不是簡單的表示式,它們將產生意想不到的結果。它們展開後是這樣的:
volume=(num++)*(num++)*(num++);
很顯然,結果是
10*11*12,
而不是10*10*10;
那麼怎樣安全的使用
cube
巨集呢?必須把可能產生***的操作移到巨集呼叫的外面進行:
int num=8+2;
volume=cube(num);
num++;
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()
最後程式的輸出為
: 123
aabbcc
千萬別擔心,除非需要或者巨集的用法恰好和手頭的工作相關,否則很少有程式設計師會知道
##運算子。絕大多數程式設計師從來沒用過它。
三、條件編譯指令
條件編譯指令將決定那些**被編譯,而哪些是不被編譯的。可以根據表示式的值或者某個特定的巨集是否被定義來確定編譯條件。
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
指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告資訊。
**:
C語言條件編譯詳解
預處理程式提供了條件編譯的功能。可以按不同的條件去編譯不同的程式部分,因而產生不同的目標 檔案。這對於程式的移植和除錯是很有用的。條件編譯有三種形式,下面分別介紹 ifdef 識別符號 程式段1 else 程式段2 endif 它的功能是,如果識別符號已被 define命令定義過則對程式段1進行編譯...
C語言條件編譯詳解
指令 用途 空指令,無任何效果 include 包含乙個源 檔案 define 定義巨集 undef 取消已定義的巨集 if 如果給定條件為真,則編譯下面 ifdef 如果巨集已經定義,則編譯下面 ifndef 如果巨集沒有定義,則編譯下面 elif 如果前面的 if給定條件不為真,當前條件為真,則...
C 條件編譯詳解
一般情況下,在進行編譯時對源程式中的每一行都要編譯。但是有時希望程式中某一部分內容只在滿足一定條件時才進行編譯,也就是指定對程式中的一部分內容進行編譯的條件。如果不滿足這個條件,就不編譯這部分內容。這就是 條件編譯 其實這跟事物具有多樣性一樣。我們需要對不同的狀況下採取不同的操作。例如程式的執行平台...