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);
 
呼び出される関数では、 va_list 型のオブジェクトが宣言されていなければならない。このオブジェクトが va_start(), va_arg(), va_end() の各マクロによって扱われる。
引き数 last は引き数リストのうち、可変な部分の直前に置かれる引き数の名前であ る。つまり呼び出された関数が型を知っている最後の引き数である。
この引き数はレジスタ変数や関数、配列として 宣言してはならない。この引き数のアドレスが va_start() マクロで用いられるかもしれないからである。
va_start() マクロの直後に va_arg() を最初に実行すると、 last の次の引き数が返る。続けて実行すると、残りの引き数がそれぞれ返る。
次の引き数がなかったり、 type が次の引き数の実際の型と互換でない場合 (デフォルトの引き数変換で扱 えなかった場合) には、予測できないエラーが起こる。
ap が va_arg(ap,type) の形で関数に渡されると、 ap の値は関数から返って来た後は不定となる。
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 を用いるシステムもある。
歴史的なセットアップは以下のとおりである。
#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
マクロに aq}aq を含み、
va_end
マクロに対応する aq{aq を含むシステムもあるので、
この二つのマクロは同じ関数になければならない。
 
#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 aqsaq:              /* string */
            s = va_arg(ap, char *);
            printf("string %s\n", s);
            break;
        case aqdaq:              /* int */
            d = va_arg(ap, int);
            printf("int %d\n", d);
            break;
        case aqcaq:              /* 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);
}