次の方法で共有


va_arg、va_end、va_start

更新 : 2011 年 1 月

可変個引数リストにアクセスします。

type va_arg(
   va_list arg_ptr,
   type 
);
void va_end(
   va_list arg_ptr 
);
void va_start(
   va_list arg_ptr,
   prev_param 
); // (ANSI version)
void va_start(
   arg_ptr 
);  // (Pre-ANSI-standardization version)

パラメーター

  • type
    取得する引数の型。

  • arg_ptr
    引数リストへのポインター。

  • prev_param
    省略可能な最初の引数の直前のパラメーター (ANSI のみ)。

戻り値

va_arg マクロは現在の引数を返します。va_start マクロと va_end マクロには戻り値はありません。

解説

va_argva_endva_start の各マクロを使用すると、関数が可変個の引数をとる場合に、移植性の高い方法で関数の引数にアクセスできます。 2 つのバージョンのマクロがあります。STDARG で定義されているマクロ。H は ANSI C 標準に準拠しています。 VARARGS で定義されているマクロ。H は廃止され、下位互換性維持します。 使用する ANSI の標準化に想定されました。

これらのマクロにより、関数は、固定数の省略可能な引数の変数の数字が続く、必須の引数がかかります。 必須引数は関数の通常のパラメーターとして宣言され、パラメーター名でアクセスできます。 省略可能な引数には、STDARG.H または VARARGS.H 内のマクロでアクセスします。これらのマクロは、引数リスト内の最初の省略可能な引数へのポインターを設定し、リストから引数を取得し、引数の処理が完了した時点でポインターをリセットします。

STDARG.H で定義されている ANSI C 準拠のマクロの使用方法は、次のとおりです。

  • 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 にリセットします。

C++ メモ :C++ メモ

VARARGS で定義されているマクロ。H は廃止予定であり、後方互換性のためにのみ存在します。 STDARGS で定義されたマクロを使用します。H は ANSI 標準の前にコードを使用している場合を除き。

/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*
}

必要条件

ヘッダー:<stdio.h> および <stdarg.h>

従来のヘッダー:<varargs.h>

ライブラリ

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
 */

#include <stdio.h>
#include <stdarg.h>
int average( int first, ... );

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. */
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 );
}

出力

Average is: 3
Average is: 8
Average is: 0

同等の .NET Framework 関数

System::ParamArrayAttribute クラス

参照

参照

引数へのアクセス

vfprintf、_vfprintf_l、vfwprintf、_vfwprintf_l

履歴の変更

日付

History

理由

2011 年 1 月

Pre-ANSI 標準化バージョンについての情報を明らかにしました。

カスタマー フィードバック