2026/09/02

C 言語の可変引数マクロ

C 言語の debug で画面表示やデバッグログ出力などで、 関数にするとオーバーヘッドがかかってしまう場合によく利用されるのが #define によるマクロ定義です。

  1#define     debug       fprintf(stderr, "debug");
    
この様に定義する事でコンパイル時(正確にはコンパイル時に実行されるプリプロセッサにより)に debugfprintf(... に置き換えられます。
  1#define     debug       fprintf(stderr, "debug")
  2    :
  3    :
  4debug;
    
この方法では fprintf(3) には情報を渡せませんが C 言語のマクロ定義は関数の形式で定義すると引数を渡す事が可能です。
  1#define     debug(_arg)     fprintf(stderr, _arg)
  2    :
  3    :
  4debug("error")
    
この様に定義する事でマクロ debug を経由して fprintf(3) に引数を渡すことができます。 ただし、引数の数は固定なので frpintf(stderr, "error: %d", errno) の様な処理は出来ません。 そこで便利なのが可変の引数を受け取りマクロを定義する __VA_ARGS__ です。 この __VA_ARGS__ を指定する事でマクロに可変引数を指定する事ができます。
  1#define     debug(...)      fprintf(stderr, __VA_ARGS__)
  2    :
  3    :
  4debug("error\n");
  5debug("%s %n\n", name, errno);
    
指定方法はマクロ定義の仮引数リストの可変部分に省略記号 (...) を指定し、 置換される文字列部分では __VA_ARGS__ を指定するだけです。 省略記号の ... は本当にドット . を 3 個つなげて書きます。
  1#ifdef      DEBUG                                           \
  2#define     debug(...)                                      \
  3{                                                           \
  4    FILE    *_fp;                                           \
  5                                                            \
  6    if((_fp = fopen("ログファイル", "a")){                  \
  7        fprintf(_fp, __VA_ARGS__);                          \
  8        fclose(_fp);                                        \
  9    }                                                       \
 10}
 11#else
 12#define     debug(...)
 13#endif
    
この様なマクロ定義をしておくことでコンパイル時に DEBUG が定義された場合 (コンパイル時に -D DEBUG が指定された場合)でログファイルへの書き込みが可能な場合は ログファイル にログを出力させる事ができます。
マクロは 1 行で記述する必要があるので改行は \ でエスケープしています。 もちろん C 言語の文法的には改行なしで書いても全然問題ないですが、 解読性のために改行を追加しています)。

__VA_ARGS__ は 1999 年に制定されたC言語の国際標準規格 ISO/IEC 9899:1999 (C99) で公式に導入されたので現在では完全に合法な記法で安心して利用できます。 ANSI X3.159-1989 (C89) までは __VA_ARGS__ が導入されていなかったので 引数の数に応じて複数のマクロを定義したりする必要がありました (それならちゃんと可変引数の関数定義したほうが良いですよね...)。
  1#define     debug1(_arg1)           fprintf(stderr, _arg1);
  2#define     debug2(_arg1, _arg2)    fprintf(stderr, _arg1, _arg2);
  3    :
  4    :
    

トラックバック
https://blog.bsdhack.org/index.cgi/Computer/20260902.trackback
コメント














メッセージ: Ready to post a comment.


Copyright © 2008-2020 Mitzyuki IMAIZUMI. All rights reserved.