Cprogramming-c-preprocessors

提供:Dev Guides
移動先:案内検索

C-プリプロセッサー

  • Cプリプロセッサ*はコンパイラの一部ではありませんが、コンパイルプロセスの別のステップです。 簡単に言えば、Cプリプロセッサは単なるテキスト置換ツールであり、実際のコンパイルの前に必要な前処理を行うようコンパイラに指示します。 CプリプロセッサをCPPと呼びます。

すべてのプリプロセッサコマンドは、ハッシュ記号(#)で始まります。 最初の非空白文字である必要があります。読みやすくするために、プリプロセッサディレクティブは最初の列から開始する必要があります。 次のセクションでは、すべての重要なプリプロセッサディレクティブをリストします-

Sr.No. Directive & Description
1

#define

プリプロセッサマクロを置き換えます。

2

#include

別のファイルから特定のヘッダーを挿入します。

3

#undef

プリプロセッサマクロの定義を解除します。

4

#ifdef

このマクロが定義されている場合、trueを返します。

5

#ifndef

このマクロが定義されていない場合、trueを返します。

6

#if

コンパイル時の条件が真かどうかをテストします。

7

#else

  1. ifの代替。
8

#elif

  1. elseと#ifを1つのステートメントで。
9

#endif

プリプロセッサー条件付きを終了します。

10

#error

エラーメッセージを標準エラー出力に出力します。

11

#pragma

標準化された方法を使用して、コンパイラに特別なコマンドを発行します。

プリプロセッサの例

以下の例を分析して、さまざまなディレクティブを理解してください。

#define MAX_ARRAY_LENGTH 20

このディレクティブは、MAX_ARRAY_LENGTHのインスタンスを20に置き換えるようにCPPに指示します。 定数に_#define_を使用して、読みやすくします。

#include <stdio.h>
#include "myheader.h"

これらのディレクティブは、CPPに System Libraries からstdio.hを取得し、現在のソースファイルにテキストを追加するように指示します。 次の行は、CPPにローカルディレクトリから myheader.h を取得し、現在のソースファイルにコンテンツを追加するよう指示します。

#undef  FILE_SIZE
#define FILE_SIZE 42

既存のFILE_SIZEの定義を解除し、42として定義するようにCPPに指示します。

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

MESSAGEがまだ定義されていない場合にのみ、MESSAGEを定義するようにCPPに指示します。

#ifdef DEBUG
  /*Your debugging statements here*/
#endif

DEBUGが定義されている場合、囲まれたステートメントを処理するようにCPPに指示します。 これは、コンパイル時に_-DDEBUG_フラグをgccコンパイラーに渡す場合に便利です。 これによりDEBUGが定義されるため、コンパイル中にオンザフライでデバッグをオンまたはオフにできます。

定義済みマクロ

ANSI Cは多くのマクロを定義しています。 それぞれをプログラミングで使用できますが、事前定義されたマクロを直接変更しないでください。

Sr.No. Macro & Description
1

DATE

「MMM DD YYYY」形式の文字リテラルとしての現在の日付。

2

TIME

「HH:MM:SS」形式の文字リテラルとしての現在時刻。

3

FILE

これには、現在のファイル名が文字列リテラルとして含まれています。

4

LINE

これには、10進定数として現在の行番号が含まれます。

5

STDC

コンパイラがANSI標準に準拠する場合、1として定義されます。

次の例を試してみましょう-

#include <stdio.h>

int main() {

   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );

}

ファイル test.c の上記のコードがコンパイルされ実行されると、次の結果が生成されます-

File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1

プリプロセッサ演算子

Cプリプロセッサは、マクロの作成に役立つ次の演算子を提供しています-

マクロ継続(\)演算子

通常、マクロは1行に限定されます。 マクロ継続演算子(\)は、1行には長すぎるマクロを継続するために使用されます。 たとえば-

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

文字列化(#)演算子

文字列化演算子または番号記号演算子( '#')をマクロ定義内で使用すると、マクロパラメーターが文字列定数に変換されます。 この演算子は、指定された引数またはパラメーターリストを持つマクロでのみ使用できます。 たとえば-

#include <stdio.h>

#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Carole and Debra: We love you!

トークンの貼り付け(##)演算子

マクロ定義内のトークン貼り付け演算子(##)は、2つの引数を組み合わせます。 マクロ定義内の2つの別個のトークンを単一のトークンに結合できます。 たとえば-

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   tokenpaster(34);
   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

token34 = 40

この例は、プリプロセッサから次の実際の出力になるため、そうなりました-

printf ("token34 = %d", token34);

この例では、token ## nのtoken34への連結を示しています。ここでは、 stringizetoken-pasting の両方を使用しています。

Defined()演算子

プリプロセッサの defined 演算子は、定数式で使用され、#defineを使用して識別子が定義されているかどうかを判断します。 指定された識別子が定義されている場合、値はtrue(ゼロ以外)です。 シンボルが定義されていない場合、値はfalse(ゼロ)です。 定義された演算子は次のように指定されます-

#include <stdio.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   printf("Here is the message: %s\n", MESSAGE);
   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Here is the message: You wish!

パラメータ化されたマクロ

CPPの強力な機能の1つは、パラメーター化されたマクロを使用して機能をシミュレートする機能です。 たとえば、次のように数値を二乗するコードがあります-

int square(int x) {
   return x *x;
}

私たちは次のようにマクロを使用してコードの上に書き換えることができます-

#define square(x) ((x)* (x))

引数を持つマクロは、使用する前に*#define *ディレクティブを使用して定義する必要があります。 引数リストは括弧で囲まれ、マクロ名の直後になければなりません。 マクロ名と左括弧の間にスペースは使用できません。 たとえば-

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));
   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Max between 20 and 10 is 20