Compartilhar via


Funções com listas de argumentos variáveis (C++)

Declarações de funções que contêm reticências (...) como o último argumento aceitam um número variável de argumentos. O C++ fornece verificação de tipo somente para os argumentos declarados explicitamente. Você pode usar listas de argumentos variáveis quando o número e os tipos de argumentos para a função podem variar. A printf família de funções é um exemplo de funções que têm listas de argumentos variáveis.

Funções com argumentos variáveis

Para acessar argumentos após os declarados, use as macros contidas no arquivo <stdarg.h> de inclusão padrão, conforme explicado neste artigo.

Seção específica da Microsoft

O Microsoft C++ permite que as reticências sejam especificadas como um argumento se as reticências forem o último argumento e uma vírgula vier antes das reticências. Portanto, a declaração int Func( int i, ... ); é legal, mas int Func( int i ... ); não é.

Fim da seção específica da Microsoft

A declaração de uma função que usa um número variável de argumentos requer pelo menos um argumento de espaço reservado, mesmo que não seja usado. Se esse argumento de espaço reservado não for fornecido, não haverá como acessar os argumentos restantes.

Quando argumentos de tipo char são passados como argumentos variáveis, eles são convertidos em tipo int. Da mesma forma, quando argumentos de tipo float são passados como argumentos variáveis, eles são convertidos em tipo double. Os argumentos de outros tipos estão sujeitos às promoções integral e de ponto flutuante comuns. Para obter mais informações, consulte Conversões Padrão.

As funções que exigem listas de variáveis são declaradas usando as reticências (...) na lista de argumentos. Use os tipos e macros descritos no <stdarg.h> arquivo de inclusão para acessar argumentos que são passados por uma lista de variáveis. Para obter mais informações sobre essas marcos, confira va_arg, va_copy, va_end, va_start.

O exemplo a seguir mostra como usar as macros para processar uma lista de argumentos variáveis:

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

O exemplo anterior ilustra estes conceitos importantes:

  1. Você deve estabelecer um marcador de lista como uma variável de tipo va_list antes que argumentos de variáveis sejam acessados. No exemplo anterior, o marcador é chamado vl.
  2. Os argumentos individuais são acessados usando a macro va_arg. Você deve informar à macro va_arg o tipo de argumento a ser recuperado para que ela possa transferir o número de bytes correto da pilha. Se você especificar um tipo incorreto de um tamanho diferente do fornecido pelo programa de chamada para va_arg, os resultados serão imprevisíveis.
  3. É necessário converter explicitamente o resultado obtido usando a macro va_arg no tipo desejado.
  4. Você deve chamar a va_end macro para encerrar o processamento de argumentos variáveis.