C マクロは何に役立ちますか?

これは、マクロの命名にあまり反映されていないようです。 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;}
...

関数をオーバーロードできないためです。

条件付きコンパイルとファイル インクルード (マクロ言語の一部でもあります) は言うまでもありません...