C言語で可変長引数を取る関数を定義する
可変長引数とは、printf
関数が取るような、あらかじめ個数が決まっていない形式の引数のことである。
例えば、自分用のprintf
を新たに定義したいとすると、引数の部分は次のように書く。
void myprintf(char *fmt, ...) { }
こう書くと、fmt
に続く引数が可変になる。
...
の前には引数が複数あってもよいが、...
の後に引数があってはならない。
つまり、...
は引数の最後でなければならない。
渡された可変長引数を使うには、stdarg.h
で定義されている型やマクロを使う。以下にそれらの使い方の例を示す。
#include <stdio.h> #include <stdarg.h> void myprintf(char *fmt, ...) { va_list ap; va_start(ap, fmt); char *p = fmt; while (*p) { if (*p == 'd') { printf("%d ", va_arg(ap, int)); p++; continue; } if (*p == 'c') { printf("%c ", va_arg(ap, char)); p++; continue; } fprintf(stderr, "不正な文字\n"); exit(1); } printf("\n"); }
va_list
型は引数のリストをイテレートするためのポインタを表す。
"va"はおそらく可変超引数を表す英語variadic argumentsの略。
va_start(ap, fmt)
によって、ap
がfmt
に続く引数のリストの先頭を指している状態になる。
一般にva_start
の第二引数には...
の直前の引数の識別子を指定する。
引数のリストを順番に調べるには、va_arg
マクロを使う。va_arg(ap, int)
はap
が指している位置の引数をint
型として返し、ap
が指す位置を一つ先に進める。
myprintf
関数は簡易的なprintf
を実現する。具体的には、d
とc
からなる文字列と可変長引数を受け取り、可変長引数を参照しながら、d
を整数に、c
を文字に置き換える。
例えばmyprintf("dcdcd", 1, 'a', 2, 'b', 3)
を呼び出すと1 a 2 b 3
と表示される。