C言語学習ノート(五)前処理記号
前処理の「常識」について前処理はコンパイルではなく、「前コンパイル」でもない. 前処理は、各言語にあるわけではありません. C/C++前処理は、ソースプログラムを個々のセグメント(phase)に分割して整理するだけで、コンパイルは行われない. プリプロセッサは、UNIXの従来ではPPと略記されており、自動構築スクリプトでは、CプリプロセッサはCPPのマクロフィンガーと略記されている.曖昧さをもたらさないために、C++(c-plus-plus)はCPPと略されるのではなく、CXXに変更されることが多い.
C言語プリプロセッシング符号
ANSI C規格でサポートされている前処理記号は以下のとおりです.
#define、#undef(マクロ定義),#include(ファイルに含む),#if、#else、#elif、#endif、#ifdef、#ifndef、#ifndef(条件コンパイル),#line(行制御),#error(エラー処理),#pragma(実装関連),#(エスケープ),#(パラメータ接続)
マクロ定義の注意事項
マクロを使用してコメント記号を定義しようとすると、次のコードなどのコードが使用できません.
注釈は、前処理命令処理よりも先に処理されるため、これらのマクロ定義を展開すると、自然にエラーが発生します.
マクロが式を定義するときは、カッコをけちけちしてはいけません.これは説明する必要はありません.
マクロを定義するときは、マクロ名にスペースを入れないほうがいいです.次の定義は多くのトラブルをもたらします.
いったん#undefを使用してマクロを取り消すと、再定義しない限り、後のコードはこのマクロを使用できません.また、undefがない場合は直接再定義し、後の定義は前の定義を上書きします.次のコードのc値は4です.
マクロは使用時にのみ展開されます.そうしないと、定義に問題があってもコンパイルエラーは発生しません.上のコードの2番目のdefineを注釈し、Cの値を0にすると、X定義が取り消されても、Yが使用されていないため、展開されません.
#pragmaの共通パラメータ
Message:コンパイルウィンドウ出力情報に対応情報を表示するために使用します.次のようなアプリケーションがあります.
code_seg:ドライバを開発するときに使います.
once:このファイル(一般的にはヘッダファイル)を一度だけコンパイル(確認)することを指定します.
HDrstop:後のヘッダファイルをコンパイルしないことを示します.
pack:メモリの位置合わせパラメータを指定します.
#記号と##記号
#記号はエスケープに使用されます.そう言えば理解しにくいですが、例を見てみましょう.
PRTSQR(4)を実行すると、この文の出力は次のとおりです.
The sqr of x is 16.
パラメータの値を表示する場合は、文字列の文字xの前に#を付け、引用符を付けます.
出力結果は次のようになります.
The sqr of 4 is 16.
##演算子は、次のマクロなどの接続に使用されます.
上の2行目のコードはx 8に展開されます.
プリプロセッシングシンボルについてはここまでまとめておきます.
C言語プリプロセッシング符号
ANSI C規格でサポートされている前処理記号は以下のとおりです.
#define、#undef(マクロ定義),#include(ファイルに含む),#if、#else、#elif、#endif、#ifdef、#ifndef、#ifndef(条件コンパイル),#line(行制御),#error(エラー処理),#pragma(実装関連),#(エスケープ),#(パラメータ接続)
マクロ定義の注意事項
マクロを使用してコメント記号を定義しようとすると、次のコードなどのコードが使用できません.
#define BSC //
#define BMC /*
#define EMC */
BSC my single-line comment
BMC my multi-line comment EMC
注釈は、前処理命令処理よりも先に処理されるため、これらのマクロ定義を展開すると、自然にエラーが発生します.
マクロが式を定義するときは、カッコをけちけちしてはいけません.これは説明する必要はありません.
マクロを定義するときは、マクロ名にスペースを入れないほうがいいです.次の定義は多くのトラブルをもたらします.
#define SUM (x) ((x)*(x))
いったん#undefを使用してマクロを取り消すと、再定義しない限り、後のコードはこのマクロを使用できません.また、undefがない場合は直接再定義し、後の定義は前の定義を上書きします.次のコードのc値は4です.
#include
#define X 3
#define Y X*2
#undef X
#define X 2
int c = Y;
int main(int argc, char** argv){
printf("%d",c) ;
return 0;
}
マクロは使用時にのみ展開されます.そうしないと、定義に問題があってもコンパイルエラーは発生しません.上のコードの2番目のdefineを注釈し、Cの値を0にすると、X定義が取り消されても、Yが使用されていないため、展開されません.
#pragmaの共通パラメータ
Message:コンパイルウィンドウ出力情報に対応情報を表示するために使用します.次のようなアプリケーションがあります.
#ifdef _X86
#pragma message("x86 macro is activated.");
#endif
code_seg:ドライバを開発するときに使います.
once:このファイル(一般的にはヘッダファイル)を一度だけコンパイル(確認)することを指定します.
HDrstop:後のヘッダファイルをコンパイルしないことを示します.
pack:メモリの位置合わせパラメータを指定します.
#記号と##記号
#記号はエスケープに使用されます.そう言えば理解しにくいですが、例を見てみましょう.
#define PRTSQR(x) printf("The sqr of x is %d.
", ((x)*(x)));
PRTSQR(4)を実行すると、この文の出力は次のとおりです.
The sqr of x is 16.
パラメータの値を表示する場合は、文字列の文字xの前に#を付け、引用符を付けます.
#define PRTSQR(x) printf("The sqr of "#x" is %d.
", ((x)*(x)));
出力結果は次のようになります.
The sqr of 4 is 16.
##演算子は、次のマクロなどの接続に使用されます.
#define XNAME(n) x##n
int XNAME(8);
上の2行目のコードはx 8に展開されます.
プリプロセッシングシンボルについてはここまでまとめておきます.