1. 程式人生 > >#ifndef 與#ifdef的用法

#ifndef 與#ifdef的用法

防止重複編譯以test.h為例:#ifndef TEST_H#define TEST_H.#endif一般是用來防止重複包含標頭檔案第一次包含標頭檔案時 XXX沒有被定義 第二次再用時 XXX 已經被定義拉就不在包含這個標頭檔案。條件指示符#ifndef檢查預編譯常量在前面是否已經被定義.如果在前面沒有被定義,則條件指示符的值為真,於是從#inndef到#endif之間的所有語句都被包含進來進行處理.相反,如果#inndef指示符的值為假,則它與#endif指示符之間的行將被忽略.條件指示符#ifndef 的最主要目的是防止標頭檔案的重複包含和編譯。

深入:條件編譯

預處理程式提供了條件編譯的功能。可以按不同的條件去編譯不同的程式部分,因而產生不同的目的碼檔案。這對於程式的移植和除錯是很有用的。條件編譯有三種形式,下面分別介紹:

1. 第一種形式:

#ifdef 識別符號
程式段1
#else
程式段2
#endif

它的功能是,如果識別符號已被 #define命令定義過則對程式段1進行編譯;否則對程式段2進行編譯。如果沒有程式段2(它為空),本格式中的#else可以沒有,即可以寫為:
#ifdef 識別符號
程式段

#endif

舉例如下:
#define NUM ok
void main()

{
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
#ifdef NUM
printf("Number=%d/nScore=%f/n",ps->num,ps->score);
#else
printf("Name=%s/nSex=%c/n",ps->name,ps->sex);
#endif
free(ps);
}

由於在程式的第16行插入了條件編譯預處理命令,因此要根據NUM是否被定義過來決定編譯那一個printf語句。而在程式的第一行已對NUM作過巨集定義,因此應對第一個printf語句作編譯故執行結果是輸出了學號和成績。在程式的第一行巨集定義中,定義NUM表示字串OK,其實也可以為任何字串,甚至不給出任何字串,寫為: #define NUM 也具有同樣的意義。 只有取消程式的第一行才會去編譯第二個printf語句。讀者可上機試作。

2. 第二種形式:
#ifndef 識別符號
程式段1
#else
程式段2
#endif
與第一種形式的區別是將“ifdef”改為“ifndef”。它的功能是,如果識別符號未被#define命令定義過則對程式段1進行編譯,否則對程式段2進行編譯。這與第一種形式的功能正相反。

3. 第三種形式:
#if 常量表達式
程式段1
#else
程式段2
#endif

它的功能是,如常量表達式的值為真(非0),則對程式段1 進行編譯,否則對程式段2進行編譯。因此可以使程式在不同條件下,完成不同的功能
舉例如下:
#define R 1
void main()

{
float c,r,s;
printf ("input a number: ");
scanf("%f",&c);
#if R
r=3.14159*c*c;
printf("area of round is: %f/n",r);
#else
s=c*c;
printf("area of square is: %f/n",s);
#endif
}

本例中採用了第三種形式的條件編譯。在程式第一行巨集定義中,定義R為1,因此在條件編譯時,常量表達式的值為真,故計算並輸出圓面積。上面介紹的條件編譯當然也可以用條件語句來實現。但是用條件語句將會對整個源程式進行編譯,生成的目的碼程式很長,而採用條件編譯,則根據條件只編譯其中的程式段1或程式段2,生成的目標程式較短。如果條件選擇的程式段很長,採用條件編譯的方法是十分必要的。