可変長引数
可変長引数関数は異なる個数の引数を用いて呼ぶことができる関数です。
以下の形で宣言できます。
void foo(char *fmt, ...);
仮引数リストの最後かつ少なくとも1個の名前付き引数の後でなければなりません。
関数呼び出しの際、可変長引数リストの部分に当たる実引数には、デフォルト引数昇格
と呼ばれる特別な暗黙の変換が適用されます。
**可変長引数の個数を取得することは出来ません。**そのため、関数側には何らかの形で引数の個数や終わりを知らせる必要があります。
引数へのアクセス方法
可変長引数を使用する関数の本体では、それらの引数の値は ライブラリの機能を用いてアクセスできます。
関数 | 詳細 |
---|---|
va_start | 可変長引数関数の引数にアクセスできるようにします。 |
va_arg | 可変長引数関数の次の引数にアクセスします。 |
va_copy | 可変長引数関数の引数をコピーします。 |
va_end | 可変長引数関数の引数の巡回を終了します |
va_list | va_start, va_arg, va_end, va_copyで使用される情報を保存します。 |
va_startがopen関数、va_endがclose関数にようなイメージです。
SYNOPSIS
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_copy(va_list dest, va_list src);
void va_end(va_list ap);
サンプルコード
#include <stdarg.h>
#include <stdio.h>
void foo(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
while (fmt != NULL)
{
printf("%s\n", fmt);
fmt = va_arg(ap, char*);
}
va_end(ap);
}
int main()
{
foo("aiueo", "test", "aaaaaa", NULL);
return 0;
}
va_copyのサンプルコード
C言語関数辞典 - va_copyのコードを参考にしています。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>
void sum_product(double *sum, double *product, int n, ...)
{
va_list ap;
va_list dest;
int i;
/* nからスタートさせているのがポイントです */
va_start(ap, n);
va_copy(dest,ap);
*sum = 0.0;
*product = 0.0;
/* 総和 */
for ( i = 0; i < n; i++ )
*sum += va_arg(ap, double);
/* 総乗 */
*product = va_arg(dest, double);
for ( i = 1; i < n; i++ )
*product *= va_arg(dest, double);
va_end(ap);
va_end(dest);
}
int main(void) {
double sum, product;
sum_product(&sum, &product, 4, 1.0, 2.0, 3.0, 4.0);
printf("総和: %.1f\n", sum);
printf("総乗: %.1f\n", product);
return EXIT_SUCCESS;
}