可変長引数の関数

va_listという型があり、これを使って可変長引数リストを操作できる。
va_listは、SYSTEM_DATA_TYPES(7)に説明がある。

example

#include <stdio.h>

static void myprintf(char *first_arg, ...) {
  va_list ap;
  va_start(ap, first_arg);
  printf("%s\n", va_arg(ap, char *));
  printf("%d\n", va_arg(ap, int));
  va_end(ap);

}
int main(int argc, char **argv) {
  myprintf("first", "second", 3);
  return 0;
}

output

second
3

va_listを操作するマクロ

va_start

void va_start(va_list ap, last)

apを初期化する。 lastに指定するのは可変長引数の直前の引数。

va_end

void va_end(va_list ap);

va_listを他の関数でも使えるように、va_startを呼び出したら、その関数内でva_endは呼び出すことになっている。
va_endを呼び出すと、va_listはundefinedになる。

va_arg

type va_arg(va_list ap, type);

apが現在指している値の次の値を取得し、apが指すポイントを一つ進める。
va_startを呼び出した直後はapは可変長引数の直前の引数を指しているので、va_argをよびだすと、可変長引数の先頭の引数が返る。

va_copy

void va_copy(va_list dest, va_list src);

va_listの値をコピーするのに使用する。
srcが指す引数の位置ポインタの情報も含めてコピーする。
va_copyを呼び出したら、va_endでfreeしてやる必要がある。

example

#include <stdio.h>

static void myprintf(char *first_arg, ...) {
  va_list ap;
  va_start(ap, first_arg);
  printf("1. ap: %s\n", va_arg(ap, char *));

  va_list aq;
  va_copy(aq, ap);
  printf("1. aq: %s\n", va_arg(aq, char *));
  printf("2. ap: %s\n", va_arg(ap, char *));
  va_end(ap);
  va_end(aq);
}
int main(int argc, char **argv) {
  myprintf("first", "second", "third", "forth");
  return 0;
}

example

1. ap: second
1. aq: third
2. ap: third