2010-12-02 13 views
21

可能性の重複:
C/C++: Passing variable number of arguments aroundマクロの代わりにC関数内で__VA_ARGS__を使用する方法は?

私は現在、私のCファイルで宣言次のマクロを使用しています。

#define COMMON_Print(...) printf (__VA_ARGS__) 

今、その呼び出しがうまく動作しますが、私は次のようになりますC関数を作成できるようにする必要があることが判明:

void COMMON_Print(...) 
{  
    printf (__VA_ARGS__); 
} 

だから機能が動作しない、I

"未定義の識別子__VA_ARGS__エラー" のエラーが表示されます私のプロジェクトの複雑さは、インターフェイスなので、関数を持つ必要があります...どうすればパラメータを取得し、printf関数に渡すことができますか?それとも、私は間違って何をしていますか?

ありがとうございます!

+1

このhttp://stackoverflow.com/questions/205529/cc-passing-variable-number-of-argumentsを参照してください。 -around – Kos

答えて

36

?printfの各関数は、対応するv?printf関数を持ちますが、同じことをしますが、可変引数リストはva_listです。

#include <stdio.h> 
#include <stdarg.h> 

void COMMON_Print(char *format, ...) 
{ 
    va_list args; 

    va_start(args, format); 
    vprintf(format, args); 
    va_end(args); 
} 

サイドノート:va_startがパラメータとして...前の最後の引数の名前を取ること注意してください。 va_startは、いくつかのスタックベースのマジックを使用して可変引数を取得するマクロで、これを行うには最後の固定引数のアドレスが必要です。

この結果、少なくとも1つの固定引数があるため、va_startに渡すことができます。これが、より簡単なCOMMON_Print(...)宣言ではなく、format引数を追加した理由です。

を参照してください:http://www.cplusplus.com/reference/clibrary/cstdio/vprintf/

+0

マクロを使用する場合、先行するargは必要ありません。この例を考えてみましょう: '#define LOGI(...)((void)__ android_log_print(ANDROID_LOG_INFO、LOG_TAG、_​​_VA_ARGS __))'これは明らかに、使用の観点から非常に便利です。 –

15

__VA_ARGS__はマクロだけのためです。 variadic関数はかなり異なっています。それらを処理するにはva_start,va_argおよびva_endからstdarg.hを使用する必要があります。

まず、あなたの関数は、例えば、少なくとも1つの名前付きパラメータを必要とします。

void COMMON_Print(const char* fmt, ...) 

次にあなたがva_listを定義し、それを設定するためにva_startを使用することができます。

va_list args; 
va_start(args, fmt); 
// your code here 
va_end(args); 

今、あなたがargsを使用することができます引数にアクセスする。 va_arg(args, TYPE)を呼び出すと、次の可変引数が返されるので、すべての引数を読むまで呼び出すことができます。

あなただけprintfを呼び出そうとしている場合は、直接va_listかかりvprintfと呼ばれるprintfの変種があります:

vprintf(fmt, args); 

をから別の可変引数関数を呼び出すための簡単な方法はありませんが。 vprintfのようなものが必要ですva_list

+0

あなたの説明をありがとう。彼らが本当に助けてくれた助けと説明に感謝します! :) – Jona

+0

'va_arg(args、TYPE)'は、NULLが呼び出し元によって渡された場合にのみNULLを返します。 va_argのデフォルトの終了条件はありません。センチネル値を渡すか、パラメータによって渡されたパラメータの正確な数を知っているか、printf形式の文字列中の%の数を数えなければなりません。 –

+0

@tristopiaああ、そうですね。私は必要に応じて最後にNULLを渡す習慣になっています。固定 –

4

__VA_ARGS__はマクロのみです。

可変数の引数を別の関数に連鎖させることは直接できません。代わりに にva_listを渡す必要があり、呼び出す関数はva_listを取らなければなりません。幸いにも、これを行うのprintfのばらつきがあります、あなたの関数はこのように書かれる必要があります:

void COMMON_Print(char *format,...) 
{  
    va_list args; 
    va_begin(args,format); 
    vsprintf(format,args); 
    va_end(args); 
} 
+1

お返事ありがとうございます!それは実際に動作します!しかし、私は私が信じている私の最後に解決する必要があるいくつかの書式設定の問題が続いています。参考までに、私は組み込み機器に取り組んでいます。 – Jona

+0

vaprintfとは何ですか?それとも、それは単にタイプミスですか? –

関連する問題