2016-06-24 2 views
2

関数の最初の引数をva_listに含めることはできますか?ある関数から別の関数に引数を渡したい。私が欲しい最初の引数をva_listオブジェクトに含める

int main(){ 
    test(1,2,3,4,5,-1); 
} 

void test(int firstArg, ...){ 
    va_list va; 
    va_start(va, firstArg); 
    passFunction(va); 
} 

void passFunction(va_list va){ 
    int x;  
    while((x = va_arg(ap,int))!=-1){ 
     cout << x << endl; 
    } 
} 

出力:

1 
2 
3 
4 
5 

実際の出力:

2 
3 
4 
5 

が明示的に関数に最初の引数を渡すことなく、これを達成する方法はありますか?

va_start()
+1

を使用可能な可変引数テンプレートを持っている場合は、私は、:それはあなたのコンパイラとの互換性がある場合は、ちょうど、それを直接コーディングすることができるように

いずれかの方法で、プリプロセッサによって生成されたコードは、ほぼ同じになってしまいますそれらを代わりに使用することを推奨します。 – chris

+1

私はそれらを使用することはできません、私はそれらを呼び出すC関数を持っているので、テスト関数の引数はCと互換性がなければなりません。 –

+1

タグC++と 'cout << x << endl;で投稿を複雑にするのはなぜですか? 'printf("%d \ n "、x);' – chux

答えて

0

は、固定パラメータを必要とし、指定されたパラメータ次パラメータにva_listを初期化します。あなたの関数には固定パラメータが1つしかないので、va_start()を使用してva_listに含めるオプションはありません。その前に固定パラメータがないからです。 32ビットのみで

(64ビットは、はるかに複雑である)、あなたがあなた自身のソースファイルにコンパイラのソースvarargs.hからva_start()またはstdargs.hためのコード(または同等のコード)をコピーしてva_argを初期化するために、それを微調整することができますそれに続くアドレスではなく、指定されたパラメータ自体のアドレスを使用します。だから、あなただけの+__size(parmN)部分削除します

#ifdef __cplusplus 
#define va_start(ap, parmN) ((void)((ap) = (std::va_list)((char _FAR *)(&parmN)+__size(parmN)))) 
#else 
#define va_start(ap, parmN) ((void)((ap) = (va_list)((char _FAR *)(&parmN)+__size(parmN)))) 
#endif 

:C++ Builderで、va_start()は次のように定義されて

は、例えば、Visual Studioで

#ifdef __cplusplus 
#define my_va_start(ap, parmN) ((void)((ap) = (std::va_list)((char _FAR *)(&parmN)))) 
#else 
#define my_va_start(ap, parmN) ((void)((ap) = (va_list)((char _FAR *)(&parmN)))) 
#endif 

を、va_start()は次のように定義されています。

#define _crt_va_start(ap,v) (ap = (va_list)_ADDRESSOF(v) + _INSIZEOF(v)) 
#define va_start _crt_va_start 

だから、電子+ _INSIZEOF(v)部分:

#define my_va_start(ap,v) (ap = (va_list)_ADDRESSOF(v)) 

あなたはおそらくそのva_start()源を得ることができないので、GCCは実際に、コンパイラ組み込み関数の代わりにマクロを使用しますが、生成されたコードはcdecl呼び出し規約(のみ呼び出し規約そのため、類似していなければなりません32ビットで可変パラメータをサポート)は、コンパイラ間でかなり標準化されています。

void test(int firstArg, ...){ 
    va_list va = (va_list) &firstArg; 
    passFunction(va); 
} 
+0

これはとても役に立ちました。ありがとうございました –

+0

ダミーのパラメータを追加してva_startを変更するのではなく、 'passFunction'を呼び出すダミーの内部関数を持つ方が良いでしょう。 – user1952500

+0

@ user1952500:ダミー関数を直接呼び出すことができないため、ダミー関数をインラインアセンブリーして、ダミーパラメーターを正しく挿入するために呼び出しスタックを操作する必要があります。 –

関連する問題