[C#, CSharp, C Sharp 教學 教程 教材 Tutorial] 前置處理指示詞(Preprocessor Directive)
YehYeh\'s Notepad yehyeh@gmail.com 

[C#, CSharp] 前置處理指示詞

前置處理指示詞(Preprocessor Directive)

  • 前置處理指示詞(Preprocessor Directive):用來指示編譯器如何進行編譯的程式,執行時沒有作用
    前置處理指示詞
    • 前置處理指示詞的種類:
      • 宣告指示詞:#define、#undef
      • 條件式編譯指示詞:#if、#elif、#else、#endif
      • 診斷指示詞:#error、#warning
      • Line指示詞:#line
      • 區域指示詞:#region、#endregion
      • pragma指示詞:#pragma
    • 不可以使用/* */方式註解前置處理指示詞
      • #if A
            XXX
        //#elif B       // O
            //XXX       // O
        #elif C
            /* XXX */   // O
        /*              // X 不可使用此方式註解前置處理指示詞
        #else
        */              // X
            XXX
        #endif
        
Δ 回到最上方

宣告指示詞

  • 宣告指示詞:用來定義或取消定義條件式編譯符號
    • 定義一個符號
      • #define 符號
    • 取消符號定義
      • #undef 符號
    • #define只能出現在程式的第一個語彙基元之前
    • 同一個符號多次定義或是多次取消定義都是合法的
    • #define 符號1    //定義符號
          XXX
      #undef 符號1     //取消定義符號
      
    • #define 符號2
      #define 符號2    // O 多次定義同名符號
      
      #undef 符號2
      #undef 符號2
      #undef 符號2     // O 多次取消符號定義
      
Δ 回到最上方

條件式編譯指示詞

  • 條件式編譯指示詞:條件式包含排除某段原始碼
    • 判斷指定符號是否有定義,有定義就編譯區塊內的程式碼
      • #if 符號1
             ... //#if區塊的內容
        [#elif 符號2]opt
             ... //#elif區塊的內容
        [#elif 符號3]opt
             ... //#elif區塊的內容
        #elseopt
             ... //#else區塊的內容
        #endif
      • #if和#endif一定要成對出現,#elif及#else則不一定要有
      • #if和#endif之間可以沒有#elif或有1個以上#elif
      • #if和#endif之間可以沒有#else或1個#else,且不能出現在#elif之前
      • 條件式編譯指示詞中條件不成立的區塊,編譯時會被略掉,即使有錯誤的語法也可以通過編譯
        • #define 除錯
          #define 測試
          
          #if 除錯
              System.Console.WriteLine(" Debug ");    // 條件成立,會被編譯
          #elif 測試                   // 因為#if條件成立,所以不會被編譯
              for(int i = 0; (({      // 錯誤語法,因條件不成立,所以不會被編譯
          #else                       // 因為#if條件成立,所以不會被編譯
              for(int j = 0; ))}      // 錯誤語法,不會被編譯
          #endif
          
      • 如果#if後面接續的符號有定義,就會將該區塊含入編譯 #elif及#else區塊不會被編譯
      • 如果#if後面接的符號沒有定義,則會依序判斷#elif是否成立,成立則將該區塊含入編譯
      • 如果#if及#elif後面接續的符號都沒有定義,則將#else所屬區塊含入編譯
      • 如果#if及elif後面接續的符號皆無定義且沒有#else,則#if、#endif內的程式碼都不編譯
    • 逐字字串常值中若出現條件式編譯指示詞,會被視做一般字串處理
      • #define 除錯
        
        #if 除錯
        //下面的#else會被視為一般字串,而非條件式編譯指示詞
        System.Console.WriteLine(@" deubg
        #else
            XXX
        ");
        #endif
        
    • 註解可能會干擾條件式編譯指示詞
      • #define 除錯
        
        #if 除錯
            /*
        #else                             //除錯成立時 ⇒ #else會被視為註解
            /* */ Console.Write("Hello"); //顯示: Hello
        #endif
        
      • #undefine 除錯
        
        #if 除錯
            /*
        #else                               //else 成立
            /* */ Console.Write("Hello");   //顯示: Hello
        #endif
        
Δ 回到最上方

診斷指示詞

  • 診斷指示詞:產生編譯時期的錯誤(Error)和警告(Warning)
    • 產生一個錯誤
      • #error 錯誤訊息opt
      • 訊息可不加雙引號即會被視為字串
    • 產生一個警告
      • #warning 警告訊息opt
      • 訊息可不加雙引號即會被視為字串
    • #if 除錯版本
          #warning 除錯版
      #elif 正式版本
          #warning 正式版
      #else
          #error   錯誤版本
      #endif
      
Δ 回到最上方

行號指示詞

  • Line指示詞:改變編譯器輸出的行號或檔名
    • 改變編譯及除錯時的行號
      • #line 新行號
        • 可以指定行號,會影響編譯器輸出及除錯
        • 只改變行號,不改變程式執行流程
        • 可能會造成無法正確除錯
        • 很少被使用到
        • 通常用於原始程式碼和編譯的程式碼不同的時候,例如以某個縮寫代表某段常用的程式碼,所以編譯前需用程式將縮寫代換成程式碼,而代換後的行號可能和原始程式碼不同
    • 改變編譯及除錯時的行號及檔案名稱
      • #line 新行號 檔名
    • 回復或取消之前的行號或檔名設定
      • #line default
    • 在除錯時隱蔽某段程式碼 ⇒ 該段程式碼仍會被執行
      • #line hidden
        • 在偵錯時略過後續的程式碼
        • 可用來縮小要偵錯的程式碼範圍
        • 只影響偵錯,不影響行號及錯誤訊息回報
        • 在ASP中可以使用#line hidden來區別程式碼是使用者設計或是自動產生
          •     Console.Write("1");     //可以偵錯
            #line hidden
                Console.Write("2");     //偵錯時會略過,但程式碼會被執行
                Console.Write("3");     //偵錯時會略過,但程式碼會被執行
            #line default
                Console.Write("4");     //可以偵錯
            
    • using System;
      
      class Program
      {
          static void Main(string[] args)
          {
              Console.Write("1");
      #line 5
      #warning 第1次警告
              Console.Write("2");
      #line 10
      #warning 第2次警告
              Console.Write("3");
      #line 10 "新檔名.cs"
      #warning 第3次警告
              Console.Write("3");
      #line hidden
      #warning 第4次警告
              Console.Write("4");
      #line default
      #warning 第5次警告
              Console.Write("5");
          }
      }
      

      #line及#warning使用範例
Δ 回到最上方

區域指示詞

  • 區域指示詞
    • 標示出某段程式碼的範圍,並加以描述
    • #region 訊息1opt
      ...
      #endregion 訊息2opt
    • #region     程式碼開始
          Console.Write("程式碼");
      #endregion  程式碼結束
      
    • 區域指示詞可以放在條件式編譯指示詞內,也可以含括住編譯指示詞
      • #if 除錯
            #region    程式碼開始     // #region不可放在條件式編譯指示詞中間
        #endif
            Console.Write("程式碼");
        #endregion  程式碼結束
        
    • 區域指示詞不可以和條件式編譯指示詞交叉使用
      • #if 除錯
            #region     程式碼開始    // #region不可放在條件式編譯指示詞中間
        #endif
            Console.Write("程式碼");
            #endregion  程式碼結束
        
Δ 回到最上方

pragma指示詞

  • pragma警告指示編譯器啓用或停用特定警告,及產生總和檢查碼(checksum)以便協助ASP .Net程式偵錯
    • 啓用特定警告
      • #pragma warning restore 警告編號1, 警告編號2, ...
    • 停用特定警告
      • #pragma warning disable 警告編號1, 警告編號2, ...
    • 警告編號請參考:MSDN 編譯器錯誤
Δ 回到最上方