va_arg,va_end va_start

存取變數引數清單。

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_startva_end不傳回值。

備註

va_argva_end,以及va_start巨集提供可移植的方式來存取函式的引數,當函式接收不定個數引數。 有可用的巨集的兩個版本: STDARG 中所定義的巨集。H 符合 ANSI C 標準。 VARARGS 中所定義的巨集。H 已經過時,保留用於回溯相容性。 它們的設計使用 ANSI 標準化之前的方法。

這些巨集假設函式使用固定的數目的必要引數,後面接著多個選擇性引數。 必要的引數宣告為一般函式參數,可以透過參數名稱。 選擇性的引數被經由 STDARG 中的巨集。H 或 VARARGS。H,設定第一個選擇性的引數,引數清單中的指標,請從清單中,擷取引數時,並重設指標引數處理完成。

ANSI C 標準,定義的巨集在 STDARG 中。H,使用方法如下:

  • va_start設定arg_ptr與第一個引數清單中的選擇性引數傳遞給函數。 引數arg_ptr必須要有va_list型別。 引數prev_param是必要的參數,前面的第一個選擇性引數,引數清單中的名稱。 如果prev_param暫存器的儲存類別,以巨集的行為未定義宣告。 va_start必須先使用va_arg用於第一次。

  • va_arg擷取的值, type所給定的位置從arg_ptr增量arg_ptr以指向下一個引數,在清單中,使用了大小的type決定何處開始下一個引數。 va_arg可以是任何數目的函式內的時間擷取時使用到引數清單。

  • 擷取所有的引數之後, va_end會重設滑鼠指標以 NULL

C++ 注意事項C++ 注意事項

VARARGS 中所定義的巨集。H 已取代且存在於僅供回溯相容性。使用 STDARGS 中所定義的巨集。H,除非您正在使用之前的 ANSI 標準的程式碼。

編譯與時/clr (Common Language Runtime 編譯),使用這些巨集的程式可能會產生非預期的結果,因為原生和通用語言執行階段型別系統之間的差異。 此程式,請考慮:

#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預期它的第二個參數是int或char*。 傳入的引數是 0xffffffff ( unsigned int、 不int) 和NULL (實際int, char*)。 當編譯的原生程式碼時,程式會產生輸出

-1
(null)

不過,當以編譯/clr:pure,型別不符會導致程式產生例外狀況。 解決方法是使用明確轉換 (cast):

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 );
}

Output

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

.NET Framework 對等用法

System::ParamArrayAttribute 類別

請參閱

參考

引數的存取

vfprintf、 _vfprintf_l、 vfwprintf、 _vfwprintf_l