Available in

(3) (3)/de (3)/es (3)/fr (3)/ja (3)/pl (3)/pt (3head)

TOC

STDARG(3)                  Linux Programmer's Manual                 STDARG(3)



名樵前

       stdarg, va_start, va_arg, va_end, va_copy - 個数・型が可変な引数リスト

書饉式

       #include <stdarg.h>

       void va_start(va_list ap, last);
       type va_arg(va_list ap, type);
       void va_end(va_list ap);
       void va_copy(va_list dest, va_list src);

説睫明

       関数は呼び出しに際して、個数や型が可変な引数をとることがでい襦
       インクルードファイル  <stdarg.h>  では  va_list   型が宣言されており、3
       つのマクロが定義されている。これらを用いると、
       呼び出された関数側では個数や型を知らない引た瑤離螢好箸髻⊇腓飽
       つづつ読み込むことがでい襦

       呼び出される関数では、                                          va_list
       型のオブジェクトが宣言されていなければならない。このオブジェクトが
       va_start(), va_arg(), va_end() の各マクロによって扱われる。

   va_start()
       va_start()       マクロは最初に呼び出さなければならない。これは      ap
       を初期化し、 va_arg() と va_end() で用いることがでい襪茲Δ砲垢襦

       パラメーター                        last                         は引-
       数リストのうち、可変な部分の直前に置かれるパラメーターの名前であ
       る。つまり呼び出された関数が型を知っている最後の引た瑤任△襦

       このパラメーターはレジスタ変数や関数、配列として
       宣言してはならない。このパラメーターのアドレスが             va_start()
       マクロで用いられるかもしれないからである。

   va_arg()
       va_arg()                  マクロは、呼び出し時に指定された引た瑤里Δ繊
       次の位置にあるものを指定した型  type  の値として取得する。 パラメーター
       apva_list ap で、  va_start()  によって初期化されている必要がある。
       va_arg()                       を呼び出すごとに                      ap
       は変更され、次回の呼び出しの際に、さらに次の引た瑤鯤屬垢茲Δ砲覆襦
       パラメーター      type     は型の名前である。     type     の前に     *
       を付ければ、オブジェクトへの型付ぅ櫂ぅ鵐燭得られる。

       va_start() マクロの直後に va_arg() を最初に実行すると、 last の次の引-
       数が返る。続けて実行すると、残りの引た瑤それぞれ返る。

       次の引た瑤なかったり、    type   が次の引た瑤亮尊櫃侶燭噺澳垢任覆ぞ豺
       (デフォルトの引た変換で扱        えなかった場合)        には、予測で-
       ないエラーが起こる。

       apva_arg(ap,type)      の形で関数に渡されると、      ap
       の値は関数から返って来た後は不定となる。

   va_end()
       va_start()       が実行される毎に、同じ関数内で対応する        va_end()
       が実行されなければならない。   va_end(ap)   が呼び出された後、変数   ap
       の値は不定となる。           va_start()           と           va_end()
       の組を何回も並べて使うことも可能である。                       va_end()
       はマクロかもしれないし関数かもしれない。

   va_copy()
       すぐ分かる                  va_list                  の実装は、variadic
       な関数のスタックフレームのポインタである。
       このような場合(ほとんどはそうである)、
       単に以下のようにすればいいように思える。

           va_list aq = ap;

       残念ながら、(長さ          1の)ポインタの配列として扱うシステムもある。
       そのような場合、以下のようにする必要がある。

           va_list aq;
           *aq = *ap;

       最後に、パラメータをレジスタで渡すシステムの場合、           va_start()
       でメモリを割り当て、パラメータを格納し、
       次のパラメータがどれかを指し示すようにする必要がある。 そして  va_arg()
       でリストを順番にたどり、     va_end()    で割り当てたメモリを開放する。
       このような状況に対応するため、C99   では   va_copy()   マクロを追加し、
       前述のような割り当ては以下のように置ご垢┐蕕譴襪茲Δ砲靴拭

           va_list aq;
           va_copy(aq, ap);
           ...
           va_end(aq);

va_copy()           が実行されるごとに、           対応する           va_end()
を同じ関数内で実行しなければならない。 この名前はまだ draft proposal  なので、
va_copy() の代わりに __va_copy を用いるシステムもある。

準犁拠

       va_start(),  va_arg(),  va_end() マクロは C89 準拠である。 va_copy() は
       C99 で定義されている。

注躇意

       これらのマクロは、以前から用いられてい親嬰のマクロ群と
       互換では2甬遒里發里噺澳垢淵弌璽献腑鵑蓮     インクルードファイル
       <varargs.h> に存在する。

       歴史的なセットアップは以下のとおりである。

           #include <varargs.h>

           void
           foo(va_alist)
               va_dcl
           {
               va_list ap;

               va_start(ap);
               while (...) {
                   ...
                   x = va_arg(ap, type);
                   ...
               }
               va_end(ap);
           }

       va_start   マクロに   '{'   を含み、   va_end   マクロに対応する    '}'
       を含むシステムもあるので、
       この二つのマクロは同じ関数になければならない。

バ丱グ

       varargs       マクロとは異なり、       stdarg        マクロでは固定引-
       数なしで関数を指定することが許されていない。       これは       varargs
       ベースのコードを             stdarg             のコードに書ご垢┐襪箸-
       に、面倒な作業のもとになる。        また、すべての引た瑤       va_list
       として可変個指定したいような場合 (vfprintf(3) など) にも障害となる。

       関数                                                                foo
       は書式文字からなる文字列を受け入れ、その書式文字に対応する型で可変個の
       引た瑤鯑匹濆み、印字する。

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

       void
       foo(char *fmt, ...)
       {
           va_list ap;
           int d;
           char c, *s;

           va_start(ap, fmt);
           while (*fmt)
               switch (*fmt++) {
               case 's':              /* string */
                   s = va_arg(ap, char *);
                   printf("string %s\n", s);
                   break;
               case 'd':              /* int */
                   d = va_arg(ap, int);
                   printf("int %d\n", d);
                   break;
               case 'c':              /* char */
                   /* need a cast here since va_arg only
                      takes fully promoted types */
                   c = (char) va_arg(ap, int);
                   printf("char %c\n", c);
                   break;
               }
           va_end(ap);
       }



                                  2001-10-14                         STDARG(3)

COMMENTS

Add your comment here. Whitespace and linebreaks are preserved. URLs are linked automatically.
CAPTCHA

No HTML allowed. URLs will be linked with nofollow attribute. Whitespace is preserved.