C/C++マクロ定義の可変パラメータ詳細解析

2030 ワード

コードを書く過程で、デバッグ情報を画面に出力することが多く、printfのような関数が呼び出されます.しかし、デバッグが解決したら、これらの場所を手動で削除したり、コメントしたりする必要があります.最近『Linux Cプログラミングワンストップ学習』という本を読んで、一つの方法を思いついた.
 
  
void myprintf(char* fmt, ...)
{
}
#ifdef DEBUG
#define printf(fmt, args...) myprintf(fmt, ##args)
#endif

デバッグ段階でDEBUGデバッグを持って、正式にオンラインになるとprintfを空の関数にすることができます.
このような潜在的なリスクの1つは、glib関数を暗記してprintf出力エラーlogを呼び出す必要があり、キャンセルされる可能性があります.
幸いなことに、glib呼び出しの大部分はfprintfであるべきである.
問題は解決したがargsには...そして##argsはまだよくわかりません.インターネットでgccマニュアルの資料を探しました.
可変パラメータを持つマクロ(Macros with a Variable Number of Arguments)
1999年版のISO C規格では、マクロは関数のように、定義時に可変パラメータを持つことができる.マクロの構文と関数の構文は似ています.
次に例を示します.
 
  
#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

ここで,「...」は可変パラメータを指す.このようなマクロは、呼び出されると、0個以上の符号として表され、中のカンマを含めて右括弧が終わるまで表示される.呼び出されると、マクロボディ(macro body)では、中の__VA_ARGS_識別子の代わりに、それらの記号シーケンスのセットが表示される.より多くの情報はCPPマニュアルを参照することができる.
GCCは常に複雑なマクロをサポートしており、異なる構文を使用して、他のパラメータと同じように可変パラメータに名前を付けることができます.たとえば、次の例を示します.
 
  
#define debug(format, args...) fprintf (stderr, format, args)

これは、上述したISO C定義のマクロ例と全く同じであるが、このように書くと可読性が高く、説明が容易である.
GNU CPPには、上記の2つのフォーマットの定義フォーマットをサポートする2つのより複雑なマクロ拡張があります.
標準Cでは、可変パラメータを省略することはできませんが、空のパラメータを渡すことができます.たとえば、次のマクロ呼び出しはISO Cでは不正です.文字列の後ろにカンマがないからです.
 
  
debug ("A message")

GNU CPPはこの場合、可変パラメータを完全に無視することができます.上記の例では、コンパイラに問題があります.マクロが開くと、中の文字列の後ろに余分なカンマがあるからです.
この問題を解決するために、CPPは特殊な‘##’操作を使用する.
書式は次のとおりです.
 
  
#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

ここで、可変パラメータが無視されたり、空になったりした場合、‘###’操作はプリプロセッサ(preprocessor)に前のカンマを除去させます.マクロ呼び出し時に、確かにいくつかの可変パラメータが提供された場合、GNU CPPも正常に動作し、これらの可変パラメータをカンマの後ろに配置します.他のpasted macroパラメータのように、これらのパラメータはマクロの拡張ではありません.
具体的には「Linux Cプログラミングワンストップ学習」を参照して、ついでにこの本をほめて、よく書けました!