複製鏈接
請複製以下鏈接發送給好友

#ifndef

鎖定
#ifndef是"if not defined"的簡寫定義的一種,它是可以根據是否已經定義了一個變量來進行分支選擇,一般用於調試等。實際上確切的説這應該是預處理功能中三種(宏定義,文件包含條件編譯)中的第三種——條件編譯
中文名
#ifndef
外文名
#ifndef(if not defined)
作用1
防止頭文件的重複包含和編譯
作用2
便於程序的調試和移植
配套使用
#endif
類    型
宏定義條件編譯

目錄

#ifndef定義

#define x //定義一個宏
...
//C語言在對程序進行編譯時,會先根據預處理命令進行“預處理”。C語言編譯系統包括預處理,編譯和鏈接等部分。
#ifndef x //先測試x是否被宏定義過
#define x
程序段1 //如果x沒有被宏定義過,定義x,並編譯程序段 1
#else
程序段2 //如果x已經定義過了則編譯程序段2的語句,“忽視”程序段 1
#endif//終止if

#ifndef作用

條件指示符#ifndef的最主要目的是防止頭文件的重複包含和編譯。條件編譯當然也可以用條件語句來實現, 但是用條件語句將會對整個源程序進行編譯,生成的目標代碼程序很長,而採用條件編譯,則根據條件只編譯其中的程序段1或程序段2,生成的目標程序較短。如果條件選擇的程序段很長,採用條件編譯的方法是十分必要的。

#ifndef內容

#ifndef 標識1 //判斷"標識1"是否定義,如果被定義則返回假,如果沒有被定義則返回真。
/**********************************/
語句1 #ifndef 標識1
語句2 #define 標識1
語句3 #endif
語句4 ……
語句5 ……
該段代碼意思是:如果標識1沒有被定義,則重定義標識1,即執行語句2、語句3;如果標識1已經被定義,則直接跳過語句2、語句3,直接執行語句4、語句5、……
/***********************************/
備註:#ifndef 和 #endif 要一起使用,如果丟失#endif,可能會報錯。
需要注意的是,#ifndef起到的效果是防止一個源文件兩次包含同一個頭文件,而不是防止兩個源文件包含同一個頭文件。網上很多資料對這一細節的描述都是錯誤的。事實上,防止同一頭文件被兩個不同的源文件包含這種要求本身就是不合理的,頭文件存在的價值就是被不同的源文件包含。
假如你有一個C源文件,它包含了多個頭文件,比如頭文件A和頭文件B,而頭文件B又包含了頭文件A,則最終的效果是,該源文件包含了兩次頭文件A。如果你在頭文件A裏定義了結構體或者類類型(這是最常見的情況),那麼問題來了,編譯時會報大量的重複定義錯誤。
例如要編寫頭文件test.h,在頭文件開頭寫上兩行:
#ifndef _TEST_H
#define _TEST_H //一般是文件名的大寫
文件結尾寫上一行:
#endif
這樣一個工程文件裏同時包含兩個test.h時,就不會出現重定義的錯誤了。
分析:
當第一次包含test.h時,由於沒有定義_TEST_H,條件為真,這樣就會包含(執行)#ifndef _TEST_H和#endif之間的代碼,當第二次包含test.h時前面一次已經定義了_TEST_H,條件為假,#ifndef _TEST_H和#endif之間的代碼也就不會再次被包含,這樣就避免了重定義了。
而把頭文件的內容都放在#ifndef和#endif中,則無論頭文件會不會被多個文件引用,都需要加上這個。一般格式是這樣的:
#ifndef <標識>
#define <標識>
......
......
#endif
<標識>在理論上來説可以是自由命名的,但每個頭文件的這個“標識”都應該是唯有的。標識的命名規則一般是頭文件名全大寫,前面加下劃線,並把文件名中的“.”也變成下劃線,如:stdio.h
#ifndef _STDIO_H
#define _STDIO_H
......
#endif

#ifndef用法

c語言中,對同一個變量或者函數進行多次聲明是不會報錯的。所以如果h文件裏只是進行了聲明工作,即使不使用#ifndef宏定義,一個c文件多次包含同一個h文件也不會報錯。使用#ifndef可以避免下面這種錯誤:如果在h文件中定義了全局變量,一個c文件包含同一個h文件多次,如果不加#ifndef宏定義,會出現變量重複定義的錯誤;如果加了#ifndef,則不會出現這種錯。

#ifndef形式

“條件編譯”命令允許對程序中的內容選擇性地編譯,即可以根據一定的條件選擇是否編譯。
條件編譯的命令主要有以下幾種 :
形式1
#ifndef 標識符
#else
程序段 2
#endif
它的作用是當“標識符”沒有由#define定義過時,則編譯“ 程序段1”,否則編譯“程序段2” ,其中如果不需要編譯“程序段2”。故上述形式可以變換為:
#ifndef 標識符
#endif
形式2
#ifndef 標識符
# define 標識符
程序段 1
#else
程序段 2
#endif
它的作用是當“標識符”沒有由# define定義過。 則編譯“程序段1”。否則編譯“程序段2” ;同樣當無“程序段2”時(作用與形式1完全相同),則上述形式變換為:
#ifndef 標識符
#define 標識符
程序段 1
#endif
形式3
程序段 1
#else
程序段 2
#endif
它的作用是當“表達式”值為真時。編譯程序段1。否則則編譯程序段2。同樣,當無程序段2時,則上述形式變換為:
#if 表達式
程序段 1
#endif
以上三種形式的條件編譯預處理結構都可以嵌套使用。 當#else後嵌套 #if 時,可以使用預處理命令 # elif , 它相當於#else #if。在程序中使用條件編譯主要是為了方便程序的調試和移植。