Saturday, September 1, 2018

C - プリプロセッサ

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

すべてのプリプロセッサコマンドは、ハッシュ記号(#)で始まります。 最初の非空白文字でなければなりません。読みやすくするために、プリプロセッサ・ディレクティブは最初の列から始める必要があります。 次のセクションでは、重要なプリプロセッサディレクティブ
Sr.No.Directive & Description
1
#define
Substitutes a preprocessor macro.
2
#include
Inserts a particular header from another file.
3
#undef
Undefines a preprocessor macro.
4
#ifdef
Returns true if this macro is defined.
5
#ifndef
Returns true if this macro is not defined.
6
#if
Tests if a compile time condition is true.
7
#else
The alternative for #if.
8
#elif
#else and #if in one statement.
9
#endif
Ends preprocessor conditional.
10
#error
Prints error message on stderr.
11
#pragma
Issues special commands to the compiler, using a standardized method.

プリプロセッサの例
次の例を分析して、さまざまな指令を理解してください。

#define MAX_ARRAY_LENGTH 20

このディレクティブはCPPにMAX_ARRAY_LENGTHのインスタンスを20で置き換えるように指示します。可読性を高めるために#defineを定数に使用してください。
#include <stdio.h>
#include "myheader.h"
これらの指令は、システムライブラリからstdio.hを取得し、そのテキストを現在のソースファイルに追加するようにCPPに指示します。 次の行は、ローカルディレクトリからmyheader.hを取得し、その内容を現在のソースファイルに追加するようにCPPに指示します。
#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__
The current date as a character literal in "MMM DD YYYY" format.
2
__TIME__
The current time as a character literal in "HH:MM:SS" format.
3
__FILE__
This contains the current filename as a string literal.
4
__LINE__
This contains the current line number as a decimal constant.
5
__STDC__
Defined as 1 when the compiler complies with the ANSI standard.
Let's try the following example 
#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行では長すぎるマクロを続行するために使用されます。 例えば
#define  message_for(a, b)  \
   printf(#a " and " #b ": We love you!\n")

Stringize(#)演算子
stringizeまたは数値符号演算子( '#')は、マクロ定義内で使用すると、マクロパラメータを文字列定数に変換します。 この演算子は、指定された引数またはパラメータリストを持つマクロでのみ使用できます。 例えば
#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に連結して示しています。ここでは、stringizeとtoken-pastingの両方を使用しています。


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つは、パラメータ化されたマクロを使用して関数をシミュレートする機能です。 たとえば、次のように数値を2乗するコードがあるとします
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






No comments:

Post a Comment

Interfaces and their protocol stacks

インタフェースとそのプロトコルスタック 主要なネットワーク要素に精通した後、これら要素間のインタフェースをよりよく知る時期が来ています。 インタフェースは、MME、SGWおよびPGWが他のネットワーク要素(例えば、HSSまたはPCRF)と協働することを可能にする。 それらの...