ご存知の方もいるかもしれないがC言語には可変引数という概念がある。
一般的なC言語での関数の宣言は
int sum(int a, int b);
みたいな感じだろう。
関数定義の際に必要なのは
戻り値の型 関数名 仮引数の型 仮引数名
となる。ここで仮引数は必要な数だけ定義し、関数呼び出しの際にも、定義した型、数の実引数を渡す。
しかし、普段からよく使うあのprintf()
関数はどうなっているだろう。
様々な型の、様々な数の引数を渡しても正しく動作する。
これはprintf()
関数を前述の感覚で捉えていると違和感を覚える。
様々な型の、不特定数の引数を受け取れるようにするのが
可変引数
という仕組みだ
可変引数を用いた関数定義はprintf()
を例に取ると
int printf(const char *format, ...);
となる。
この...
の部分が可変引数の実体である。
可変引数を用いる為の関数等はstdarg.h
で定義されている。
基本的な例は
#include <stdarg.h>
void (int last, ...){
va_list ap;
va_start(ap, last);
int arg[last];
for(int i; i < last; i++){
arg[last] = va_arg(ap, int);
}
va_end(ap);
}
みたいな感じだ。
stdarg.h
受け取った複数の引数を一つにまとめる構造体。
va_start(va_list ap, last);
last
(引数郡の最初の変数)とap
を受け取り、last
以後の引数をap
に格納する。
初期化処理だと思って良い。
型を指定しap
から順番に引数を取り出す。
ap
をクリアする。
これらを上手く組み合わせることで、可変引数を受け取る関数を作れる。
以下は数値とその個数を与えると平均が帰ってくる関数
#include <stdarg.h>
float avg(int amnt, ...){
va_list list;
va_start(list, amnt);
float sum = 0;
for(int i = 0; i < amnt; i++){
sum += va_arg(list, int);
}
va_end(list);
return sum/amnt;
}