1

マクロについて読んだところによるとva_arg、引数リストが指す次の引数を取得します。配列インデックスのように、取得したい引数のインデックスを選択する方法はありますか?

たとえば、va_argマクロを少なくとも 3 回呼び出す必要がある操作を実行する必要がありますが、それらの 3 回でリストの次の引数ではなく同じ引数を取得する必要があります。1 つの解決策は、関数を使用して引数を渡すことですが、私はそれを望んでいません。

また、これを実行できるマクロが他にない場合、ポインターで配列引数の先頭を参照するにはどうすればよいですか? 移植性がなく、タイプセーフではないことなどを知っています。学習のためだけに。

これを実装する方法のサンプルコードを次に示します。

bool SQLBase::BindQuery (char* query, int NumArgs, ...) 
{ 
    va_list argList; 
    va_start(argList, NumArgs); 
    SQLPrepare (hstmt, query, SQL_NTS); 
    for (int x = 0; x < NumArgs; x++) 
    { 
        SQLBindParameter (hstmt, (x+1), GetTypeParameter (va_arg(argList, SQLPOINTER*), SQL_C_CHAR, SQL_CHAR, 10, 0, va_arg(argList, SQLPOINTER*), va_arg(argList, SQLLEN), &recvsize[x]);
    } 

va_arg は SQLBindParameter 関数に対して 3 回呼び出され、最初の 2 回は同じ引数を指し、引数リストのカウント メンバーを増やしません。

4

1 に答える 1

1

まず第一に、関数呼び出しで va_arg を複数回呼び出すのは、これらの呼び出しがどの順序で行われるかわからないため、毛むくじゃらです。引数が正しい順序で取得されるように、事前にこれを行う必要があります。

第 2 に、いいえ: va_list には配列スタイルの使用法はありません。これは、va_list がスタック上の引数について何も知らないためです。va_arg 呼び出しで型を指定すると、va_arg はその引数のサイズを知っているため、va_list に含まれる (内部/概念) ポインターを増やすことができます。3 番目の引数に到達するには、最初の 2 つの型を指定する必要があります。

すべての引数が同じサイズ (「void*」など) の場合は、適切な回数だけ va_arg を呼び出すループをいつでも作成できます。引数が実際に同じサイズであることが合理的に確信できる場合、これは「一種の」移植性があります。ただし、これを実行することが最善の方法であるとは確信していません。実行する必要があるということは、変数引数を使用する代わりに最初に配列を渡すなど、別の設定がより適切であることを示している可能性があります。関数。

関数の引数のアドレスを取得して、それらが何らかの順序でスタック上にあると想定することもできます。コンパイラ間で異なる可能性があり、コンパイルオプションに基づいて変更される可能性がある呼び出し規約について知る必要があるため、これは恐ろしく移植性がありません。私は絶対にこのようなことをしないことをお勧めします。

于 2012-07-28T10:01:39.627 に答える