動的引数


可変個数の引数の作成

これまで、C言語で用いてきた標準関数の中で
printf()関数やscanf()関数のような汎用的で、特異な関数があります

その機能は以前説明しましたが
しかし、printf()関数のように引数の数が固定でない関数を、私たちはまだ作れません
ここでは引数の数を可変的に受け取れる関数を作成してみましょう

まず、プロトタイプで引数の数は固定ではないことを示します
そのためには3つのピリオドからなる...を用います

void function(第一引数 , ...)

この場合でも、必ず第一引数は固定になります
可変にすることができるのは、第二引数以降になります

これで、可変個の引数を受け取ることができる関数を作成することができました
次に受け取った引数にアクセスする必要があります
可変個の引数にアクセスするには、まずstdarg.hヘッダファイルをインクルードします
そして、このヘッダファイルで定義されているマクロと構造体型を利用します

まず、可変個の引数リストにアクセスを開始するにはva_start()を使用します
必ずこれを最初に行う必要があります

void va_start(va_list リスト , prev);

リストには、引数リストへのポインタを指定します
これは、可変個の引数の情報を保持するための stdarg.h で定義されている標準型です
pervは、最初の可変個数の手前の固定引数を指定します(最後の固定引数)

この時点で va_list 型の変数に、可変引数の情報が格納されます
次に、この va_list 型変数から、順に可変引数の内容を呼び出します
引数リストの値を得るにはva_arg()を使用します

type va_arg(va_list リスト , type);

リストは、va_start()で渡してセットされた va_list 型変数を指定します
type は、引数リストから受け取る値の型を指定します
可変この場合、引数を受け取る時に型チェックはされないため、ここで型を明示します

引数リストは、可変個数の引数の始まり部分にセットされています
そこから、va_arg()が呼び出されるごとに次の引数を返します

最後に、すべての引数を取得したらva_end()でポインタを NULL にリセットします

void va_end(va_list リスト);

リストは、これまでva_start()やva_arg()で引数にアクセスしていた変数です
#include <stdio.h>
#include <stdarg.h>

void dynamicArgument(int , ...);

int main() {
	dynamicArgument(4 , 10 , 20 , 30 , 40);
	return 0;
}

void dynamicArgument(int arg_num , ...) {
	va_list args;
	int value , count;

	if (arg_num < 1) return;

	va_start(args , arg_num);

	for (count = 0 ; count < arg_num ; count++) {
		value = va_arg(args , int);
		printf("第%d引数 = %d\n" , count + 2 , value);
	}

	va_end(args);
	return;
}
ここでは、可変個に引数を受け取る関数 dynamicArgument() を作成しています
この関数は第一引数に引数の個数を、第二引数以降は任意のint型引数を受け取り
第二引数以降で受け取った値を、int型として標準出力に出力します

このように、可変個の引数を受け取った場合
受け取り方も動的になるため、何らかの手段で引数の個数を調べる必要があります
printf()関数などは、フォーマット指定子によって引数リストの個数と型をチェックしていますね

因みに、通常va_arg()、va_start()、va_end()は、関数ではなくマクロとして実装されています


type va_arg( va_list arg_ptr, type );

可変個の引数リストから、カレント引数の値を得ます
カレント引数は、呼び出すごとに次の引数に移行します

ヘッダ - stdarg.h
arg_ptr - 引数リストへのポインタを指定します
type - 取得する値の型を指定します

戻り値 - 現在の引数

void va_end( va_list arg_ptr );

引数リストへのアクセスを終了し、ポインタをNULLにします

ヘッダ - stdarg.h
arg_ptr - 引数リストへのポインタを指定します

void va_start( va_list arg_ptr, prev_param );

引数リスト arg_ptr の先頭をセットします

ヘッダ - stdarg.h
arg_ptr - 引数リストへのポインタを指定します
prev_param - 最初のオプション引数の直前の引数



前のページへ戻る次のページへ