2

重複の可能性:
C++ プリプロセッサ __VA_ARGS__ 引数
の数 可変数の引数を受け入れる関数に渡される引数の数をカウントする方法は?

可変パラメーター関数を学習するために、デモを作成します。

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

int foo(int n, int m, ...);

int
main (int argc, char *argv[])
{
    int n = 10;
    int m = 15;
    int p = 20;
    //foo (n, m);
    foo(n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n, int m, ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, m);
    p = va_arg (ap, int);
    n = m + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}

パラメータが 2 つしかない場合の関数の処理方法を知りたいです。(このデモでは、 と のみの​​場合nmを実行した後foo、結果を取得したい: n = n+m。)

4

4 に答える 4

1

実行時に、va_listから追加パラメーターの実際の数を知る方法はありません。したがって、この数を推測する別の方法が必要です。たとえば、前のパラメーターやリストの終わりの規則から(たとえば、任意の数のポインターの後にNULLを指定します)。を考えてみましょうprintf。ここで、フォーマット文字列は、va_list部分で予期される(どのタイプの)パラメーターの数を決定します。

これを考慮に入れる限り、パラメーターの最小数(つまり、空のva_list)について特別なことは何もありません。期待するものが何もないことがわかっている場合は、va_listから何もポップしないでください。

于 2013-01-04T15:58:04.187 に答える
1

「foo」に何をさせたいのかわかりませんが、通常、fooにはループが必要であり、fooには、呼び出されたとき、またはループが終了したときに、与えられた引数の数が通知されている必要があります。printf は %d %s %f ... で最初の char* パターン パラメータでこれを認識します

たとえば、いくつかの整数の合計を返す関数を書きたい場合は、次のように実装できます。

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

int int_sum(int count, ...) {
    int sum = 0, i;
    va_list ap;
    va_start(ap, count);
    for (i = 0; i < count; ++i) {
        sum += va_arg(ap, int);
    }
    va_end(ap);
    return sum;
}

int main() {
    printf("%d\n", int_sum(5, 1, 2, 3, 4, 5));
    return 0;
}
于 2013-01-04T16:00:27.323 に答える
1

すべての可変引数 ('variadic') 関数について、関数が処理しなければならない引数の数を知る方法が必要です。その扱い方は様々です。

  • および関数ファミリはprintf()scanf()書式文字列を使用して、関数に渡される引数の数を決定します。
  • POSIXopen()関数は、2 番目の引数のオプションを調べて、3 番目の引数があるかどうかを確認します。
  • POSIXexecl()関数は、null ポインター引数に到達するまでスキャンします。
  • 処理する引数の数を明示的に渡すことができます ( Fei Jiangのを参照)。

これらの方法はすべて機能します。このopen()メカニズムは、最も一般的ではなく、最も独特です (主に歴史的な癖から生じています)。

ただし、そのようなメカニズムの 1 つを使用する必要があります。呼び出された関数は、引数リストの変数セクションの処理がいつ終了したかを (何らかの方法で) 通知できなければなりません。

可変長引数リストを他の関数に中継しない限り (たとえばvsnprintf()、関数に渡された可変引数を使用して文字列をフォーマットするために使用する場合)、可変長関数本体には、可変数の引数を処理するためのループが必要です。関数にはそのループがありません。

于 2013-01-04T15:55:10.350 に答える
0

質問を理解したかどうかはわかりませんが、varlist 関数に foo (int n,...) のような引数が 1 つしかない場合...、その後に foo (nケース) でva_start()、常に機能します。

int foo (int n,  ...);
int
main (int argc, char *argv[])
{
    int n = 10;
    int m = 15;
    int p = 20;

    foo (n, m);
    //foo (n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n,  ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, n);
    p = va_arg (ap, int);
    n = n + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}
于 2013-01-04T15:32:28.307 に答える