1. 程式人生 > >[C/C++]#ifndef,#define用法

[C/C++]#ifndef,#define用法

1.檔案中的#ifndef  頭件的中的#ifndef,這是一個很關鍵的東西。比如你有兩個C檔案,這兩個C檔案都include了同一個標頭檔案。而編譯時,這兩個C檔案要一同編譯成一個可執行檔案,於是問題來了,大量的宣告衝突。  還是把標頭檔案的內容都放在#ifndef和#endif中吧。不管你的標頭檔案會不會被多個檔案引用,你都要加上這個。一般格式是這樣的:  #ifndef <標識>  #define <標識>  ......  #endif  <標識>在理論上來說可以是自由命名的,但每個標頭檔案的這個“標識”都應該是唯一的。標識的命名規則一般是標頭檔案名全大寫,前後加下劃線,並把檔名中的“.”也變成下劃線,如:stdio.h  #ifndef _STDIO_H_  #define _STDIO_H_  ......  #endif 2.在#ifndef中定義變量出現的問題(一般不定義在#ifndef中)

#ifndef AAA #define AAA

int i; ... #endif 裡面有一個變數定義 在vc中連結時就出現了i重複定義的錯誤,而在c中成功編譯。 結論: (1).當你第一個使用這個頭的.cpp檔案生成.obj的時候,int i 在裡面定義了當另外一個使用這個的.cpp再次[單獨]生成.obj的時候,int i 又被定義然後兩個obj被另外一個.cpp也include 這個頭的,連線在一起,就會出現重複定義. (2).把源程式副檔名改成.c後,VC按照C語言的語法對源程式進行編譯,而不是C++。在C語言中,若是遇到多個int i,則自動認為其中一個是定義,其他的是宣告。 (3).C語言和C++語言連線結果不同,可能(猜測)時在進行編譯的時候,C++語言將全域性 變數預設為強符號,所以連接出錯。C語言則依照是否初始化進行強弱的判斷的。(參考) 解決方法: (1).把源程式副檔名改成.c。 (2).推薦解決方案: .h中只宣告 extern int i;在.cpp中定義 <x.h> #ifndef __X_H__ #define __X_H__ extern int i; #endif //__X_H__ <x.c> int i; 注意問題: (1).變數一般不要定義在.h檔案中。 一般情況下,源程式中所有的行都參加編譯。但是有時希望對其中一部分內容只在滿足一定條件才進行編譯,也就是對一部分內容指定編譯的條件,這就是“條件編譯”。有時,希望當滿足某條件時對一組語句進行編譯,而當條件不滿足時則編譯另一組語句。  條件編譯命令最常見的形式為:      #ifdef 識別符號      程式段1      #else      程式段2      #endif            它的作用是:當識別符號已經被定義過(一般是用#define命令定義),則對程式段1進行編譯,否則編譯程式段2。      其中#else部分也可以沒有,即:      #ifdef      程式段1      #denif            這裡的“程式段”可以是語句組,也可以是命令列。這種條件編譯可以提高C源程式的通用性。如果一個C源程式在不同計算機系統上系統上執行,而不同的計算機又有一定的差異。例如,我們有一個數據型別,在Windows平臺中,應該使用long型別表示,而在其他平臺應該使用float表示,這樣往往需要對源程式作必要的修改,這就降低了程式的通用性。可以用以下的條件編譯:      #ifdef WINDOWS      #define MYTYPE long      #else      #define MYTYPE float      #endif            如果在Windows上編譯程式,則可以在程式的開始加上      #define WINDOWS            這樣則編譯下面的命令列:      #define MYTYPE long            如果在這組條件編譯命令之前曾出現以下命令列:      #define WINDOWS 0            則預編譯後程序中的MYTYPE都用float代替。這樣,源程式可以不必作任何修改就可以用於不同型別的計算機系統。當然以上介紹的只是一種簡單的情況,可以根據此思路設其它的條件編譯     例如,在除錯程式時,常常希望輸出一些所需的資訊,而在除錯完成後不再輸出這些資訊。可以在源程式中插入以下的條件編譯段:      #ifdef DEBUG      print ("device_open(%p) ", file);      #endif            如果在它的前面有以下命令列:      #define DEBUG            則在程式執行時輸出file指標的值,以便除錯分析。除錯完成後只需將這個define命令列刪除即可。有人可能覺得不用條件編譯也可達此目的,即在除錯時加一批printf語句,除錯後一一將printf語句刪除去。的確,這是可以的。但是,當除錯時加的printf語句比較多時,修改的工作量是很大的。用條件編譯,則不必一一刪改printf語句,只需刪除前面的一條“#define DEBUG”命令即可,這時所有的用DEBUG作識別符號的條件編譯段都使其中的printf語句不起作用,即起統一控制的作用,如同一個“開關”一樣。      有時也採用下面的形式:      #ifndef 識別符號      程式段1      #else      程式段2      #endif            只是第一行與第一種形式不同:將“ifdef”改為“ifndef”。它的作用是:若識別符號未被定義則編譯程式段1,否則編譯程式段2。這種形式與第一種形式的作用相反。      以上兩種形式用法差不多,根據需要任選一種,視方便而定。      還有一種形式,就是#if後面的是一個表示式,而不是一個簡單的識別符號:      #if 表示式      程式段1      #else      程式段2      #endif            它的作用是:當指定的表示式值為真(非零)時就編譯程式段1,否則編譯程式段2。可以事先給定一定條件,使程式在不同的條件下執行不同的功能。 作用範圍就是當前檔案啊。因為編譯是以cpp或c檔案位單位的嘛。還以這個為例: //正常程式碼 #ifdef _DEBUG      TRACE("Some information"); #else      //Now is release version, so do nothing #endif //正常程式碼 編譯時是先把所有的預編譯處理展開(比如巨集)再編譯,所以Debug模式下,編譯時的程式碼是: //正常程式碼 TRACE("Some information"); //正常程式碼 Release模式下的程式碼是: //正常程式碼 //正常程式碼