Condividi tramite


Funzioni con elenchi di argomenti variabili (C++)

Le dichiarazioni di funzione che terminano con puntini di sospensione (un'ellissi, ...), accettano un numero variabile di argomenti. C++ fornisce il controllo dei tipi solo per gli argomenti dichiarati in modo esplicito. È possibile usare elenchi di argomenti variabili quando il numero e i tipi di argomenti per la funzione possono variare. La printf famiglia di funzioni è un esempio di funzioni con elenchi di argomenti variabili.

Funzioni con elenchi di argomenti variabili

Per accedere agli argomenti dopo quelli dichiarati, usare le macro contenute nel file <stdarg.h> di inclusione standard, come illustrato in questo articolo.

Sezione specifica Microsoft

Microsoft C++ consente di specificare i puntini di sospensione come argomento se i puntini di sospensione sono l'ultimo argomento e una virgola precede i puntini di sospensione. Pertanto, la dichiarazione int Func( int i, ... ); è legale, ma int Func( int i ... ); non lo è.

Fine sezione specifica Microsoft

La dichiarazione di una funzione che accetta un numero variabile di argomenti richiede almeno un argomento segnaposto, anche se non viene usato. Se questo argomento segnaposto non viene fornito, non è possibile accedere agli argomenti rimanenti.

Quando gli argomenti di tipo char vengono passati come argomenti di variabile, vengono convertiti in tipo int. Analogamente, quando gli argomenti di tipo float vengono passati come argomenti di variabile, vengono convertiti in tipo double. Gli argomenti di altri tipi sono soggetti alle consuete promozioni a virgola mobile e integrali. Per altre informazioni, vedere Conversioni standard.

Le funzioni che richiedono elenchi di variabili vengono dichiarate usando i puntini di sospensione (...) nell'elenco di argomenti. Utilizzare i tipi e le macro descritti nel <stdarg.h> file di inclusione per accedere agli argomenti passati da un elenco di variabili. Per altre informazioni su queste macro, vedere va_arg, va_copy, va_end va_start.

Nell'esempio seguente viene illustrato come utilizzare le macro per elaborare un elenco di argomenti di variabile:

// variable_argument_lists.cpp

#include <stdio.h>
#include <stdarg.h>

//  Declaration, but not definition, of ShowVar.
void ShowVar( char *szTypes, ... );

int main() {
   ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}

// ShowVar takes a format string of the form
// "ifcs", where each character specifies the
// type of the argument in that position.
//
// i = int
// f = float
// c = char
// s = string (char *)
//
// Following the format specification is a variable
// list of arguments. Each argument corresponds to
// a format character in the format string to which
// the szTypes parameter points
void ShowVar( char *szTypes, ... ) {
   va_list vl;
   int i;

   // szTypes is the last argument specified; you must access
   // all others using the variable-argument macros.
   va_start( vl, szTypes );

   // Step through the list.
   for( i = 0; szTypes[i] != '\0'; ++i ) {
      
      union Printable_t {
         int     i;
         float   f;
         char    c;
         char   *s;
      } Printable;

      switch( szTypes[i] ) {   // Type to expect
         case 'i':
            Printable.i = va_arg( vl, int );
            printf_s( "%i\n", Printable.i );
            break;

         case 'f':
             Printable.f = va_arg( vl, double );
             printf_s( "%f\n", Printable.f );
             break;

         case 'c':
             Printable.c = va_arg( vl, char );
             printf_s( "%c\n", Printable.c );
             break;

         case 's':
             Printable.s = va_arg( vl, char * );
             printf_s( "%s\n", Printable.s );
             break;

         default:
             break;
      }
   }
   va_end( vl );
}
32.400002
a
Test string

Nell'esempio precedente vengono illustrati questi concetti importanti:

  1. È necessario stabilire un marcatore di elenco come una variabile di tipo va_list prima che venga eseguito l'accesso a qualsiasi argomento di variabile. Nell'esempio precedente il marcatore viene denominato vl.
  2. Ai singoli argomenti si accede usando la macro va_arg. È necessario indicare alla macro va_arg il tipo di argomento da recuperare in modo che sia possibile trasferire il numero corretto di byte dallo stack. Se si specifica un tipo non corretto di dimensione diversa da quella fornita dal programma chiamante a va_arg, i risultati sono imprevedibili.
  3. È necessario eseguire esplicitamente il cast del risultato ottenuto al tipo desiderato utilizzando la macro va_arg.
  4. È necessario chiamare la macro va_end per terminare l'elaborazione dell'argomento variabile.