C プリプロセッサ

C プリプロセッサ

プリプロセッサ 実際のコンパイルが始まる前にソース コードを処理するプログラムです。これらはコンパイル プロセスの一部ではありませんが、個別に動作するため、プログラマーはコンパイル前にコードを変更できます。

  • これは、C ソース コードが実行可能ファイルに変換されるときに通過する最初のステップです。
  • プリプロセッサ ディレクティブの主な種類は次のとおりです。  マクロ ファイルインクルードの条件付きコンパイルと、#undef #pragma などのその他のディレクティブ。
  • 主に、これらのディレクティブは、C コードの特定のセクションを別の C コードに置き換えるために使用されます。たとえば、「#define PI 3.14」と記述すると、PI はプリプロセッサによって 3.14 に置き換えられます。
C プリプロセッサ

C プリプロセッサの種類

上記のプリプロセッサはすべて、次の 4 つのタイプに分類できます。

マクロ

マクロ 定数を定義したり、コードがコンパイルされる前にプリプロセッサによって置き換えられる関数を作成したりするために使用されます。 2 つのプリプロセッサ #定義する そして #undef C でマクロを作成および削除するために使用されます。

#定義する トークン値
#undef トークン

ここで、前処理後、 トークン まで拡張されます 価値 プログラム内で。

例:

C
   #include         // Macro Definition   #define LIMIT 5   int     main  (){      for     (  int     i     =     0  ;     i      <     LIMIT  ;     i  ++  )     {      printf  (  '%d   n  '       i  );      }      return     0  ;   }   

出力
0 1 2 3 4  

上記のプログラムでは、コンパイルが開始される前に、単語 LIMIT が 5 に置き換えられます。 「リミット」 マクロ定義で マクロテンプレートと呼ばれます そして 「5」はマクロ展開です。

注記 マクロ定義の末尾にセミコロン (;) はありません。マクロ定義の終わりにセミコロンは必要ありません。

いくつかもあります C の定義済みマクロ これらは、プログラムにさまざまな機能を提供するのに役立ちます。

以前に定義されたマクロは、#undef プリプロセッサを使用して定義解除できます。たとえば上記のコードでは

C
   #include         // Macro Definition   #define LIMIT 5   // Undefine macro   #undef LIMIT   int     main  (){      for     (  int     i     =     0  ;     i      <     LIMIT  ;     i  ++  )     {      printf  (  '%d   n  '       i  );      }      return     0  ;   }   


出力:

 ./Solution.c: In function 'main': ./Solution.c:13:28: error: 'MAX' undeclared (first use in this function) printf('MAX is: %dn' MAX); ^ ./Solution.c:13:28: note: each undeclared identifier is reported only once for each function it appears in  

引数付きマクロ

マクロに引数を渡すこともできます。これらのマクロは関数と同様に機能します。 例えば

# 定義する foo(a b) a + b
#define func(r) r * r

これをプログラムで理解してみましょう。

C
   #include         // macro with parameter   #define AREA(l b) (l * b)   int     main  (){      int     a     =     10       b     =     5  ;          // Finding area using above macro      printf  (  '%d'       AREA  (  a       b  ));      return     0  ;   }   

出力
Area of rectangle is: 50  

説明: 上記のプログラムではマクロ エリア(lb) を乗算して長方形の面積を計算するように定義されています。 長さ(l) そして 幅(b) 。いつ エリア(a b) と呼ばれます。 (a * b) そして結果が計算されて出力されます。

参照してください C のマクロの種類 他の例と種類については、こちらをご覧ください。

ファイルのインクルード

ファイル インクルードを使用すると、外部ファイル (ヘッダー ファイル ライブラリなど) を現在のプログラムに組み込むことができます。これは通常、次のコマンドを使用して行われます。 #含む システムファイルとユーザー定義ファイルの両方を含めることができるディレクティブ。

構文

ヘッダー ファイルをインクルードするには 2 つの方法があります。

#含む
#含む 'ファイル名'

' <' そして 「>」括弧 コンパイラに次のファイルを探すように指示します。 標準ディレクトリ その間 二重引用符 ( ' ) ソース ファイルのディレクトリでヘッダー ファイルを検索するようにコンパイラに指示します。

例:

C
   // Includes the standard I/O library   #include            int     main  ()     {      printf  (  'Hello World'  );          return     0  ;   }   

出力
Hello World 

条件付きコンパイル

条件付きコンパイル を使用すると、特定の条件に応じてコードの一部を含めたり除外したりできます。これは、プラットフォーム固有のコードの作成またはデバッグに役立ちます。次の条件付きプリプロセッサ ディレクティブがあります: #if #ifdef #ifndef else #elif および #endif

構文

条件付きプリプロセッサの一般的な構文は次のとおりです。

#もし
// 何らかのコード
#エリフ
// もう少しコードを追加
#それ以外
// さらにコードを追加
#endif

#endif ディレクティブは、#if #ifdef および #ifndef 開始ディレクティブを閉じるために使用されます。

C
   #include         // Defining a macro for PI   #define PI 3.14159   int     main  (){       // Check if PI is defined using #ifdef   #ifdef PI      printf  (  'PI is defined  n  '  );   // If PI is not defined check if SQUARE is defined   #elif defined(SQUARE)      printf  (  'Square is defined  n  '  );   // If neither PI nor SQUARE is defined trigger an error   #else      #error 'Neither PI nor SQUARE is defined'   #endif   // Check if SQUARE is not defined using #ifndef   #ifndef SQUARE      printf  (  'Square is not defined'  );   // If SQUARE is defined print that it is defined   #else      printf  (  'Square is defined'  );   #endif      return     0  ;   }   

出力
PI is defined Square is not defined 

説明: このコードでは、条件付きプリプロセッサ ディレクティブ ( #ifdef #elif および #ifndef ) 特定のマクロ ( PI そして 四角 )が定義されています。 PI が定義されているため、プログラムは ' を出力します。 PI が定義されている ' その後、SQUARE が定義されていないかどうかを確認し、' を出力します。 正方形が定義されていません '。

その他の指令

主要なプリプロセッサ ディレクティブとは別に、C はコンパイラの動作とデバッグを管理するための他のディレクティブも提供します。

#プラグマ:

コンパイラーの動作を制御するための特定の命令をコンパイラーに提供します。警告セットのアライメントなどを無効にするために使用されます。

構文

#プラグマ 指令

#pragma ディレクティブの一部については、以下で説明します。 

  1. #プラグマの起動: これらのディレクティブは、プログラムの起動前 (制御が main() に渡される前) に実行する必要がある関数を指定するのに役立ちます。
  2. #プラグマ終了 : これらのディレクティブは、プログラムが終了する直前 (コントロールが main() から戻る直前) に実行する必要がある関数を指定するのに役立ちます。

C
   #include         void     func1  ();   void     func2  ();   // specifying funct1 to execute at start   #pragma startup func1   // specifying funct2 to execute before end   #pragma exit func2   void     func1  ()     {     printf  (  'Inside func1()  n  '  );     }   void     func2  ()     {     printf  (  'Inside func2()  n  '  );     }   int     main  (){      void     func1  ();      void     func2  ();      printf  (  'Inside main()  n  '  );      return     0  ;   }   

出力
Inside main()  

上記のコードは、GCC コンパイラーで実行すると、上記のような出力を生成しますが、期待される出力は次のとおりです。

期待される出力

 Inside func1() Inside main() Inside func2()   

これは、GCC が #pragma の起動または終了をサポートしていないために発生します。ただし、以下のコードを GCC コンパイラで期待される出力に使用できます。 

C
   #include         void     func1  ();   void     func2  ();   void     __attribute__  ((  constructor  ))     func1  ();   void     __attribute__  ((  destructor  ))     func2  ();   void     func1  ()   {      printf  (  'Inside func1()  n  '  );   }   void     func2  ()   {      printf  (  'Inside func2()  n  '  );   }   int     main  ()   {      printf  (  'Inside main()  n  '  );      return     0  ;   }   

出力
Inside func1() Inside main() Inside func2()  

上記のプログラムではいくつかを使用しました 特定の構文 つまり、関数の 1 つは main 関数の前に実行され、もう 1 つは main 関数の後に実行されます。

クイズの作成