可変個引数マクロを使う

この世で変わらないのは、変わるということだけだ。
スウィフト

C99規格(ISO/IEC 9899:1999 - Programming Language C)は1999年12月にISOによって規格化されたC言語の新しい規格です。従来のC言語(C89やANSI C)には含まれていない新機能が数多く規格として導入されています。以前の記事「bool型の落とし穴」で触れた_Bool型もC99の新機能の一つです。

今回、C99の新機能の中で個人的にかなり便利だと思っている「可変個引数(可変個数引数)マクロ__VA_ARGS__」と「定義済みマクロ__func__」を紹介します。

拡張マクロ機能の使用例

最近のデバッガは高機能化しているとはいえ、ログ出力(ロギング)によるデバッグが便利なケースはまだまだあります。拡張マクロ機能はこのようなログ出力の記述時に、力を発揮します。
例えば、次のようなログ出力関数があったとします。
void debug_printf(fmt, ...);
可変引数関数は従来のC言語からサポートされています。関数本体の記述方法は関連リンク(Manpage of stdarg等)を参照して下さい。

さて、このログ出力関数はデバッグ関数のため、できればデバッグ中以外は完全に無効化してしまいたいと考えます。そこで、次のようなマクロを定義しようとします。
#if defined(DEBUG)
#define DEBUG_PRINTF(fmt, ...) debug_printf(fmt, ...)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
しかし、このような可変個数の引数を持つマクロは従来定義できなかったため、このコードはコンパイルエラーになります。C99ではこのような可変個数マクロがサポートされるようになりました。C99での記述は上記とは若干違い__VA_ARGS__マクロを使用します。
#if defined(DEBUG)
#define DEBUG_PRINTF(fmt, ...) debug_printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
これで、先程の目的は達成されました。
次に、このマクロにもう少し手を加えてみましょう。ログ出力はエラー検出時に出力されることが多いと思いますので、出力コードのあるソースファイルの場所を一緒に出力しておくと何かと便利です。例えば、次のようになります。
#if defined(DEBUG)
#define DEBUG_PRINTF(fmt, ...) \
  printf("%s:%d\n", __FILE__, __LINE__); \
  debug_printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
これで、ログ出力のあるファイル名と行数が一緒に出力されるため、エラー発生箇所の特定が容易になります。しかし、実際は、ソースの行数よりも関数名の方を知りたいことの方が多いでしょう。C99で導入された定義済みマクロ__func__がこの要求に応えてくれます。
#if defined(DEBUG)
#define DEBUG_PRINTF(fmt, ...) \
  printf("%s:%d:%s\n", __FILE__, __LINE__, __func__); \
  debug_printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif
これで、関数名も出力されるようになりましたので、エラー発生箇所の識別が容易になります。

拡張マクロ機能のサポート状況

ここで紹介したC99の新機能(__VA_ARGS_と__func__)は、gccではサポートされていますが、VC++.NETではサポートされていないようです(その他のC99機能に関しても、VC++ではほとんどサポートされていません)。 非常に便利な機能なので、使用するに値すると思っていますが、移植性は低くなるということは覚えておく必要があります。移植性を考えれば、今回あげた例のようなデバッグコードのみの使用等に限定した方が良いでしょう。
# マクロなのでそもそも使いすぎない方が良いですが(^^;)

【関連記事】
printfとtypedefの微妙な関係 - 無視されがち?なformt warning
bool型の落とし穴

【関連リンク】
Manpage of STDARG
プログラミング言語Cの新機能(seclanのほえほえルーム)
定義済みマクロ__func__と可変長引き数マクロ(フリーウェア徹底活用講座)

【関連書籍】
GCC GNU C Compiler―Manual & Reference 遠藤 俊徳
GCC: The Complete Reference Arthur Griffith
新Visual C++ .NET入門 シニア編 林 晴比古

コメント

非公開コメント

トラックバック

[C言語][Windows] 可変個数引数マクロがVisual C++で未サポートな件

C99でサポートされた可変個数引数マクロ(以下のようなコード)は、MicrosoftのVisual C++では未サポート(Visual C++ 2005ではサポートされている模様)。 #define dbg(fmt, ...) printf("debug:" fmt, __VA_ARGS__) 上記のコードを、とりあえずVC++でコンパイルし

本のおすすめ

4873115655

4274065979

4822236862

4274068579

4822255131

B00SIM19YS


プロフィール

  • Author:proger
  • 組み込み関係で仕事してます

ブログ内検索