1. 程式人生 > 其它 >#if #ifdef #if defined 等幾種常用的預處理指令的區別

#if #ifdef #if defined 等幾種常用的預處理指令的區別

技術標籤:unity

在寫shader時經常會出現一些預編譯指令比如 #if #ifdef #if defined 等,有的時候會感到困惑,所以決定仔細查一下具體的使用方法,並做一個簡單的測試。

#define

#define 指令用於定義一個巨集或者常量
#define 有兩種常用的格式:

  1. #define identifier token-string 定義一個巨集,在預編譯時會把所有identifier替換成token-string,可以用更容易理解的名稱去代替一個常量,例如:#define PI 3.1415926
  2. #define identifier( argument0, ..., argumentN-1 ) token-string 定義一個類似函式一樣的巨集,例如:#define AREA(area, w, h) (area = w*h);

// #define 的使用 //
#define SOME_MACRO
#define PI 3.141593

定義巨集時使用第一種方式,當沒有指定 token-string 時,需要注意的兩點是:

  1. 這個identifier依然是被定義了的,且可以使用#if defined 或 #ifdef 檢測到的
  2. 所有identifier字元都會被移除,或者理解為所有identifier的地方都被替換成空字串。

詳細資訊可以參考 #define文件

#if

#if 是一個預處理指令,用來控制原始檔中哪一部分會被編譯。
格式是: #if condition
簡單來說就是 #if 後面的條件語句(condition)如果執行結果不為0,則該#if語句塊內的程式碼會被編譯,否則就不會被編譯。

#elif 和 #else 可以類比為常規的用於判斷條件的關鍵字 else if 和 else,區別是前面加了個#符號,用以表明該指令是在預處理階段執行,而不是執行時執行。最後,在所有判斷結束後需要用 #endif 來作為結尾,用於確定預處理語句的作用範圍。

// #if 的使用 //
#define SOME_MACRO 0
#if SOME_MACRO
    return float4(1,1,1,1);
#else
    return float4(0,0,0,1);
#endif

以上程式碼結果返回黑色

// #if 的使用 //
#define SOME_MACRO
#if SOME_MACRO
    return float4(1,1,1,1);
#else
    return float4(0,0,0,1);
#endif

以上程式碼會報錯: invalid or unsupported integer constant expression

詳細資訊可以參考 #if文件

#ifdef

#ifdef 用於判斷一個常量或者巨集是否被定義
格式是: #ifdef identifier
identifier是一個巨集或者常量,可以通過#define指令來定義,如果identifier被定義過,則#ifdef 語句塊內的程式碼會被編譯,否則不會被編譯。
#ifdef 只是判斷一個常量或者巨集是否被定義,不可以用於表示式判斷,但是#if可以,例如:

#define CONST_VALUE 3
#if CONST_VALUE > 1
    return float4(1,1,1,1);
#else 
    return float4(0,0,0,1);
#endif

#ifdef CONST_VALUE > 1      // 這樣寫會報錯 //

hlsl文件上的說法是#ifdef這種寫法只是為了相容以往版本,建議使用defined來判斷,即使用 #if defined(MACRO) 這種形式,接下來就會說到。

These directives are provided only for compatibility with previous versions of the language. The use of the defined operator with the #if directive is preferred.

詳細資訊可以參考 #ifdef文件

#if defined

這是文件裡更推薦的一種寫法
#if defined 和 #ifdef 都可以用來判斷一個巨集是否被定義,#if !defined 等同於 #ifndef。

#define SOME_MACRO

// #if defined 的使用 //
#if defined(SOME_MACRO)
    // do something //
#elif defined(OTHER_MACRO)
    // do something else //
#endif

// #ifdef 的使用 //
#ifdef SOME_MACRO
    // do something //
#endif

#ifdef OTHER_MACRO
    // do something else //
#endif

總結

  1. 如果是根據一個巨集是否被定義來決定一段程式碼要不要執行,建議使用 #if defined(MACRO) 方式
  2. 如果是根據一個表示式的值是否為0來決定一段程式碼要不要執行,建議使用 #if condition 方式
  3. #ifdef 用於判斷巨集或者常量是否被定義,不用於判斷表示式,#if 可以用於判斷表示式



作者:上午八點
連結:https://www.jianshu.com/p/5b763006b61e
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。