これは、マクロの命名にあまり反映されていないようです。 log_function_entry()
の場合、プリプロセッサをエミュレートする必要はないと思います 大きい。
ジェネリック パラメーターを操作する必要がない限り、通常はそうする必要があります。
#define max(a,b) ((a)<(b)?(b):(a))
<
を持つ任意の型で動作します
関数だけでなく、マクロを使用すると、ソース ファイル内のシンボルを使用して操作を実行できます。つまり、新しい変数名を作成したり、マクロが存在するソース ファイルと行番号を参照したりできます。
C99 では、マクロを使用して printf
などの可変長関数を呼び出すこともできます。
#define log_message(guard,format,...) \
if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);
log_message( foo == 7, "x %d", x)
形式は printf
のように機能します .ガードが真の場合、メッセージを出力したファイルと行番号とともにメッセージを出力します。関数呼び出しの場合、呼び出し元のファイルと行を認識せず、vaprintf
を使用します。 もう少し手間がかかります。
この抜粋は、C
マクロが使用され、D
でそれらを実装する方法 .
DigitalMars.com からコピー
マクロ
プリプロセッサ マクロは C
に強力な機能と柔軟性を追加します .しかし、欠点があります:
- マクロにはスコープの概念がありません。それらは、定義の時点からソースの最後まで有効です。それらは、.h ファイル、ネストされたコードなどにまたがって一帯を切り取りました。
#include
の場合 何万行ものマクロ定義を作成すると、不注意によるマクロ展開を避けることが問題になります。 - デバッガはマクロを認識しません。シンボリック データを使用してプログラムをデバッグしようとしても、マクロ自体ではなく、マクロ展開についてしか知らないデバッガーによって損なわれます。
- マクロを使用すると、ソース コードをトークン化できなくなります。以前のマクロの変更により、任意にトークンをやり直すことができるからです。
- マクロの純粋なテキストベースは恣意的で一貫性のない使用につながり、マクロを使用するコードはエラーを起こしやすくなります。 (これを解決するためのいくつかの試みは、
C++
のテンプレートで導入されました .) - マクロは、ヘッダー ファイルの「ラッパー」など、言語の表現力の不足を補うために今でも使用されています。
マクロの一般的な使用法と、対応する D の機能の列挙を次に示します。
<オール> <リ>リテラル定数の定義:
- <リ>
C
プリプロセッサの方法
#define VALUE 5
<リ>
D
方法
const int VALUE = 5;
<リ> 値またはフラグのリストの作成:
- <リ>
C
プリプロセッサの方法
int flags:
#define FLAG_X 0x1
#define FLAG_Y 0x2
#define FLAG_Z 0x4
...
flags |= FLAG_X;
<リ>
D
方法
enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 };
FLAGS flags;
...
flags |= FLAGS.X;
<リ> 関数呼び出し規則の設定:
- <リ>
C
プリプロセッサの方法
#ifndef _CRTAPI1
#define _CRTAPI1 __cdecl
#endif
#ifndef _CRTAPI2
#define _CRTAPI2 __cdecl
#endif
int _CRTAPI2 func();
<リ>
D
方法
呼び出し規約はブロック単位で指定できるため、関数ごとに変更する必要はありません:
extern (Windows)
{
int onefunc();
int anotherfunc();
}
<リ> シンプルな汎用プログラミング:
- <リ>
C
プリプロセッサの方法
テキスト置換に基づいて使用する機能を選択する:
#ifdef UNICODE
int getValueW(wchar_t *p);
#define getValue getValueW
#else
int getValueA(char *p);
#define getValue getValueA
#endif
<リ>
D
方法
D
他のシンボルのエイリアスであるシンボルの宣言を有効にします:
version (UNICODE)
{
int getValueW(wchar[] p);
alias getValueW getValue;
}
else
{
int getValueA(char[] p);
alias getValueA getValue;
}
DigitalMars の Web サイトには、さらに多くの例があります。
これらは C の上にあるプログラミング言語 (より単純な言語) であるため、コンパイル時にメタプログラミングを行うのに役立ちます。つまり、C コードを生成するマクロ コードをより少ない行と時間で作成できます。 C で直接記述します。
また、「多態的」または「オーバーロード」された「関数のような」式を書くのにも非常に役立ちます。例えば次のように定義された max マクロ:
#define max(a,b) ((a)>(b)?(a):(b))
任意の数値型に役立ちます。 C では次のように書くことはできません:
int max(int a, int b) {return a>b?a:b;}
float max(float a, float b) {return a>b?a:b;}
double max(double a, double b) {return a>b?a:b;}
...
関数をオーバーロードできないためです。
条件付きコンパイルとファイル インクルード (マクロ言語の一部でもあります) は言うまでもありません...