STDARG(3)

名前
stdarg - 個数・型が可変な引数リスト

書式
#include <stdarg.h>

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

説明
関数は呼び出しに際して、個数や型が可変な引数をとることができる。 インクルードファイル stdarg.h では va_list 型が宣言されており、3 つのマクロが定義されている。これらを用いると、 呼び出された関数側では個数や型を知らない引き数のリストを、順に一 つづつ読み込むことができる。

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

va_start マクロは最初に呼び出さなければならない。これは ap を初期化し、 va_arg と va_end で用いることができるようにする。

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

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

va_start マクロは値を返さない。

va_arg マクロは、呼び出し時に指定された引き数のうち、 次の位置にあるものを指定した型 type の値として取得する。 パラメーター ap は va_list ap で、 va_start によって初期化されている必要がある。 va_arg を呼び出すごとに ap は変更され、次回の呼び出しの際に、さらに次の引き数を返すようになる。パ ラメーター type は型の名前である。 type に単に * を前置すれば、オブジェクトへの型付きポインタが得られる。

次の引き数がなかったり、 type が次の引き数の実際の型と互換でない場合 (デフォルトの引き数変換で扱 えなかった場合) には、予測できないエラーが起こる。

va_start マクロの直後に va_arg を実行した際には、 last の次の引き数が返る。続けて実行すると、残りの引き数がそれぞれ返る。

va_end マクロは、可変な引き数リストが va_start によって初期化された関数から、正常に戻るための処理を行なう。

va_end マクロは値を返さない。

例
関数 foo は書式文字からなる文字列を受け入れ、その書式文字に対応する型で可変個の 引き数を読み込み、印字する。
    void foo(char *fmt, ...)
    {
    	va_list ap;
    	int d;
    	char c, *p, *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 */
    			c = va_arg(ap, char);
    			printf("char %c\n", c);
    			break;
    		}
    	va_end(ap);
    }

準拠
va_start, va_arg, va_end マクロは ANSI X3.159-1989 (``ANSI C'') 準拠である。

移植性
これらのマクロは、以前から用いられてきた同等のマクロ群と 互換ではない。過去のものと互換なバージョンは、 インクルードファイル varargs.h に存在する。

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