を使用する必要がある場合は、printf()
を使用しようとするため、元のコードが失敗します。 (おそらく彼らはflog
ファイルストリームを閉じて、オープンとマクロだ、表記法を与えられた)額面でlogOpen
とlogClose
文のような怪しげなポイントを取ると、コードは次のようになります。
void logPrintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap);
logClose;
va_end(ap);
va_list ap2;
va_start(ap2, fmt);
vprintf(fmt, ap2);
va_end(ap2);
}
して使用するための特段の要件はありません2つの別個の変数; va_list
;もう一度va_start()
を使用する前に、va_end()
を使用している限り、同じものを2回使用しても問題ありません。va_list
値が別の関数(このコードでvfprintf()
と)に渡され
void logPrintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
logOpen;
vfprintf(flog, fmt, ap);
logClose;
va_end(ap);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
、あなたはそれがもはや使用可能な現在の関数であると仮定してはなりません。それにはva_end()
を呼び出すだけで安全です。
このコードではva_copy()
の必要はありません。それは動作しますが、それは必要ありません。このコードでは、args1
にva_end()
を呼び出すために、呼び出し元のコードの責任であることを
void logVprintf(const char *fmt, va_list args1)
{
va_list args2;
va_copy(args2, args1);
logOpen;
vfprintf(flog, fmt, args1);
logClose;
vprintf(fmt, args2);
va_end(args2);
}
注:あなたは、そのようなあなたの関数がva_list
に合格し、あなたが二度リストを処理する必要がありますされている場合など、他の状況でva_copy()
を必要としています。確かに、標準は言う:
va_start
とva_copy
マクロ の各呼び出しは同じ関数内va_end
マクロの対応する呼び出しによってマッチされなければなりません。
logVprintf()
機能がargs1
を初期化するためにva_start
またはva_copy
のいずれかを呼び出すことはありませんので、それは合法的args1
にva_end
を呼び出すことはできません。一方、標準ではargs2
に対してva_end
を呼び出す必要があります。
logPrintf()
機能は現在logVprintf()
の観点で実施することができる。
void logPrintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
logVprintf(fmt, args);
va_end(args);
}
この構造 - va_list
と省略記号(変数引数)を取り、カバー機能を取得し、動作に渡す操作機能機能をva_list
に変換した後で作業するのが良い方法です。遅かれ早かれ、通常、va_list
引数を持つバージョンが必要です。
printfではなく、2回目にvprintfを使用する必要があります。 –