#if, #ifdef, #ifndef, #else, #elif, #endif
這些命令讓編譯器進行簡單的邏輯控制. 當一個文件被編譯時, 你可以使用這些命令使某些行保留或者是去處.
#if expression
如果表達式(expression)的值是"真"(true),那么緊隨該命令的代碼將會被編譯.
#ifdef macro
如果"macro"已經在一個#define聲明中定義了, 那么緊隨該命令的代碼將會被編譯.
#ifndef macro
如果"macro"未在一個#define聲明中定義, 那么緊隨命令的代碼將會被編譯.
一些小邊注: 命令#elif是"elseif"的一種縮寫,並且他可以想你所意願的一樣工作. 你也可以在一個#if后插入一個"defined"或者"!defined"以獲得更多的功能.
這里是一部分例子:
#ifdef DEBUG
cout << "This is the test version, i=" << i << endl;
#else
cout << "This is the production version!" << endl;
#endif
你應該注意到第二個例子比在你的代碼中插入多個"cout"進行調試的方法更簡單.
在實現不同模塊的代碼時,並且不同模塊存在復用的代碼時,可以采用預處理宏定義#ifdef來實現不同的分支處理。
1、參考
https://bbs.csdn.net/topics/210046082
2、預處理及其作用
預處理指令共有三種:
- 宏定義 #define M 2
- 條件編譯 #ifdef/#if/#elif/#else/#endif
- 文件包含 #include
預處理就是在進行編譯的第一遍詞法掃描和語法分析之前所作的工作。說白了,就是對源文件進行編譯前,先對預處理部分進行處理,然后對處理后的代碼進行編譯。這樣做的好處是,經過處理后的代碼,將會變的很精短。
這里主要講解預處理中條件編譯#ifdef/#if/#elif/#else/#endif使用的幾種方式。
3、預處理的條件編譯#ifdef/#if/#elif/#else/#endif使用的幾種方式
方式一:
#ifdef _XXXX ...程序段1... #else ...程序段2... #endif
這表明如果標識符_XXXX已被#define命令定義過則對程序段1進行編譯;否則對程序段2進行編譯。
注意:這種方式#ifdef后面只能跟一個宏變量。
方式二:
#ifndef _XXXX ...程序段1... #else ...程序段2... #endif
與方式一相反。
方式三:
#if 常量 ...程序段1... #else ...程序段2... #endif
這種方法可以將測試代碼加進來。當需要開啟測試的時候,只要將常量變1就好了。而不要測試的時候,只要將常量變0。
方式四:
#if defined(Macro1) || defined(Macro2) || defined(Macro3) ...程序段1... #elif defined(Macro4) ...程序段2... #endif
方式四這種方法比較靈活,可以使用多個宏變量的組合(或||or與&&),推薦使用這種方法!
方式五:
#if !defined(Macro1) || defined(Macro2) || defined(Macro3) ...程序段1... #elif !defined(Macro4) ...程序段2... #endif
預處理器會依次計算條件表達式,直到發現結果非 0(也就是 true)的條件表達式。預處理器會保留對應組內的源代碼,以供后續處理。如果找不到值為 true 的表達式,並且該條件式編譯區域中包含 #else 命令,則保留 #else 命令組內的代碼。
組 1、組 2 等代碼段,可以包含任意 C 源代碼,也可以包含更多的命令,包括嵌套的條件式編譯命令。在預處理階段結束時,沒有被預處理器保留以用於后續處理的組會從程序中全部刪除。
#if 和 #elif 命令
作為 #if 或 #elif 命令條件的表達式,必須是整數常量預處理器表達式。這與普通的整數常量表達式不同,主要區別在於:
(1) 不能在 #if 或 #elif 表達式中使用類型轉換運算符。
(2) 可以使用預處理運算符 defined。
(3) 在預處理器展開所有宏,並且計算完所有 defined 表達式之后,會使用字符 o 替換掉表達式中所有其他標識符或關鍵字。
(4) 表達式中所有帶符號值都具有 intmax_t 類型,並且所有無符號值都具有 uintmax_t 類型。字符常量也會受該規則的影響。intmax_t 和 uintmax_t 定義在頭文件 stdint.h 中。
(5) 預處理器會把字符常量和字符串字面量中的字符與轉義序列轉換成運行字符集中對應的字符。然而,字符常量在預處理器表達式和在后期編譯階段是否具有相同的值,取決於實現版本。
defined 運算符
一元運算符 defined 可以出現在 #if 或 #elif 命令的條件中。它的形式如下:
- defined 標識符
- defined (標識符)
如果指定的 identifier 是一個宏名稱(也就是說,它已被 #define 命令定義,並且未被 #undef 命令取消定義),則 defined 表達式會生成值 1。否則,defined 表達式會生成值 0。
defined 運算符相對於 #ifdef 和 #ifndef 命令的優點是:你可以在更大型的預處理器表達式中使用它的值。如下例所示:
- #if defined( __unix__ ) && defined( __GNUC__ )
- /* ... */
- #endif
大多數編譯器會提供預定義宏,例如上例所使用的宏,它用來識別目標系統和編譯器。因此,在 Unix 系統中,通常預先定義好了宏 __unix__,而 GCC 編譯器則會預先定義好了宏 __GNUC__。類似地,微軟 Windows 平台上的 Visual C 編譯器會自動定義好宏 _WIN32 和宏 _MSC_VER。
#ifdef 和 #ifndef 命令
你可以通過 #ifdef 和 #ifndef 命令測試某個宏是否已被定義。它們的語法是:
- #ifdef 標識符
- #ifndef 標識符
這等同於下面的 #if 命令:
- #if defined 標識符
- #if !defined 標識符
如果 identifier 不是宏名稱,則 #ifndef 標識符后面的條件代碼被保留。
這些命令可以讓編譯器進行簡單的邏輯控制,當一個文件被編譯時,你可以用這些命令去決定某些代碼的去留,
這些命令式條件編譯的命令。
常見的條件編譯的三種形式:
①第一種形式:
#if defined(或者是ifdef)<標識符(條件)>
<程序段1>
[#else
<程序段2>]
#endif
②第二種形式:
#if !defined(或者是ifndef)<標識符(條件)>
<程序段1>
[#else
<程序段2>]
#endif
③第三種形式:
#ifdef …
[#elif … ]
[#elif …]
#else …
#endif
示例:
#include <iostream>
using namespace std;
int main()
{
#if DEBUG /*或者是#ifdef DEBUG*/
cout << "條件成立,DEBUG已經定義了!" <<endl;
#else
cout << "條件不成立,DEBUG還沒定義" <<endl;
#endif
return 0;
}
//結果輸出:條件不成立,DEBUG還沒定義
//如果是添加了#define DEBUG ,輸出結果是:條件成立,DEBUG已經定義了!
#include <iostream>
using namespace std;
#define DEBUG
int main()
{
#ifdef DEBUG /*或者是#ifdef DEBUG*/
cout << "條件成立,DEBUG已經定義了!" <<endl;
#else
cout << "條件不成立,DEBUG還沒定義" <<endl;
#endif
return 0;
}
//要注意的是,如果是#define 宏名,沒有宏體如 #define DEBUG,就必須使用#ifdef或#ifndef與之對應,
//如果是#define 宏名 宏體,如 #define NUM 1,#if 和#ifdef都可以使用。
/*
#define的用法:
*/
示例二:
#include <iostream>
using namespace std;
#define NUM 10
int main()
{
#ifndef NUM
cout << "NUM沒有定義!"<<endl;
#elif NUM >= 100
cout << "NUM >100" <<endl;
#elif NUM <100 && NUM >10
cout << "10 < NUM < 100" <<endl;
#elif NUM == 10
cout << "NUM ==10" <<endl;
#else
cout << "NUM < 10" << endl;
#endif
return 0;
}
//輸出NUM ==10
#ifdef的用法
靈活使用#ifdef指示符,我們可以區隔一些與特定頭文件、程序庫和其他文件版本有關的代碼。
代碼舉例:新建define.cpp文件
運行結果:Press any key to continue
改寫代碼如下:
運行結果為:Beginning execution of main()
Press any key to continue
更一般的情況是,#define語句是包含在一個特定的頭文件中。
比如,新建頭文件head.h,在文件中加入代碼: