va_arg、va_end、va_start
更新 : 2007 年 11 月
可変個引数リストにアクセスします。
type va_arg(
va_list arg_ptr,
type
);
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr
); // (UNIX version)
void va_start(
va_list arg_ptr,
prev_param
); // (ANSI version)
パラメータ
type
取得する引数の型。arg_ptr
引数リストへのポインタ。prev_param
省略可能な最初の引数の直前のパラメータ (ANSI のみ)。
戻り値
va_arg マクロは現在の引数を返します。va_start マクロと va_end マクロには戻り値はありません。
解説
va_arg、va_end、va_start の各マクロを使用すると、関数が可変個の引数をとる場合に、移植性の高い方法で関数の引数にアクセスできます。マクロには、STDARG.H で定義されている ANSI C 準拠のマクロと、VARARGS.H で定義されている UNIX System V 準拠のマクロの 2 つのバージョンがあります。これらのマクロは次のとおりです。
va_alist
呼び出される関数のパラメータの名前 (UNIX バージョンのみ)。va_arg
現在の引数を取得するマクロ。va_dcl
va_alist の宣言 (UNIX バージョンのみ)。va_end
arg_ptr をリセットするマクロ。va_list
STDIO.H で定義されている引数リストへのポインタの typedef。va_start
省略可能な引数のリストの先頭に arg_ptr を設定するマクロ (UNIX バージョンのみ)。
どちらのバージョンのマクロでも、関数は固定数の必須引数と、その後に続く可変数の省略可能な引数をとると想定します。必須引数は関数の通常のパラメータとして宣言され、パラメータ名でアクセスできます。省略可能な引数には、STDARG.H または VARARGS.H 内のマクロでアクセスします。これらのマクロは、引数リスト内の最初の省略可能な引数へのポインタを設定し、リストから引数を取得し、引数の処理が完了した時点でポインタをリセットします。
STDARG.H で定義されている ANSI C 準拠のマクロの使用方法は、次のとおりです。
関数のすべての必須引数は、通常どおりパラメータとして宣言されます。va_dcl マクロは、STDARG.H のマクロと一緒には使用しません。
va_start マクロは、関数に渡される引数リストの最初の省略可能な引数に arg_ptr を設定します。引数 arg_ptr は va_list 型にする必要があります。引数 prev_param は、引数リスト内の最初の省略可能な引数の直前にある必須パラメータの名前です。prev_param が register ストレージ クラスで宣言される場合、マクロの動作は未定義になります。va_arg マクロを初めて使用する前に、va_start マクロを使用する必要があります。
va_arg マクロは、arg_ptr で指定した位置から type の値を取得し、次の引数の開始位置を決定する type のサイズを使用して、リスト内の次の引数を指すように arg_ptr をインクリメントします。関数内で va_arg マクロを繰り返し使用して、リストから引数を取得できます。
すべての引数の取得後に、va_end マクロはポインタを NULL にリセットします。
VARARGS.H で定義されている UNIX System V 準拠のマクロの場合は、動作が多少異なります。
関数のすべての必須引数は、通常どおりパラメータとして宣言できます。
関数の最後 (または唯一) の引数は、省略可能な引数のリストを表します。このパラメータの名前は va_alist にする必要があります。va_alist の型として定義されている va_list と混同しないでください。
va_dcl マクロは、関数定義と関数の始まりの左中かっこ ({) の間で使用します。このマクロは、終端のセミコロンを含めて va_alist のパラメータの完全な宣言として定義されます。したがって、va_dcl マクロの後にはセミコロンを付けないでください。
va_start マクロは、関数内で、関数に渡される省略可能な引数のリストの先頭に arg_ptr を設定します。va_arg マクロを初めて使用する前に、va_start マクロを使用する必要があります。引数 arg_ptr は va_list 型にする必要があります。
va_arg マクロは、arg_ptr で指定した位置から type の値を取得し、次の引数の開始位置を決定する type のサイズを使用して、リスト内の次の引数を指すように arg_ptr をインクリメントします。関数内で va_arg マクロを繰り返し使用して、リストから引数を取得できます。
すべての引数の取得後に、va_end マクロはポインタを NULL にリセットします。
/clr (共通言語ランタイムのコンパイル) を指定してコンパイルする場合、このマクロを使用するプログラムは、ネイティブと共通言語ランタイムの型システムの違いによって、予期しない結果を生成することがあります。次に例を示します。
#include <stdio.h>
#include <stdarg.h>
void testit ( int i, ...)
{
va_list argptr;
va_start(argptr, i);
if ( i == 0 ) {
int n = va_arg( argptr, int );
printf( "%d\n", n );
} else {
char *s = va_arg( argptr, char* );
printf( "%s\n", s);
}
}
int main()
{
testit( 0, 0xFFFFFFFF ); // 1st problem: 0xffffffff is not an int
testit( 1, NULL ); // 2nd problem: NULL is not a char*
}
testit では、2 番目のパラメータが int または char* であることが必要です。渡される引数は 0xffffffff (int ではなく unsigned int) と NULL (実際には char* ではなく int) です。ネイティブ コード用にコンパイルしたプログラムの出力は次のとおりです。
-1
(null)
ただし、/clr:pure を指定してこのプログラムをコンパイルすると、型の不一致による例外が発生します。これを解決するには、次のようにして明示的にキャストを使用します。
int main()
{
testit( 0, (int)0xFFFFFFFF ); // cast unsigned to int
testit( 1, (char*)NULL ); // cast int to char*
}
必要条件
ルーチン |
必須ヘッダー |
省略可能なヘッダー |
---|---|---|
va_arg |
<stdio.h> および <stdarg.h> |
<varargs.h>* |
va_end |
<stdio.h> および <stdarg.h> |
<varargs.h>* |
va_start |
<stdio.h> および <stdarg.h> |
<varargs.h>* |
* UNIX V との互換性用
互換性の詳細については、「C ランタイム ライブラリ」の「互換性」を参照してください。
ライブラリ
C ランタイム ライブラリのすべてのバージョン。
使用例
// crt_va.c
/* The program below illustrates passing a variable
* number of arguments using the following macros:
* va_start va_arg va_end
* va_list va_dcl (UNIX only)
*/
#include <stdio.h>
#define ANSI /* Comment out for UNIX version */
#ifdef ANSI /* ANSI compatible version */
#include <stdarg.h>
int average( int first, ... );
#else /* UNIX compatible version */
#include <varargs.h>
int average( va_list );
#endif
int main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );
/* Call with 4 integers. */
printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );
/* Call with just -1 terminator. */
printf( "Average is: %d\n", average( -1 ) );
}
/* Returns the average of a variable list of integers. */
#ifdef ANSI /* ANSI compatible version */
int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;
va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum += i;
count++;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#else /* UNIX compatible version must use old-style definition. */
int average( va_alist )
va_dcl
{
int i, count, sum;
va_list marker;
va_start( marker ); /* Initialize variable arguments. */
for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )
sum += i;
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#endif
出力
Average is: 3
Average is: 8
Average is: 0
.NET Framework の相当するアイテム
System::ParamArrayAttribute クラス