Comparteix a través de


Funciones con listas de argumentos de variable (C++)

Las declaraciones de función que tienen puntos suspensivos (...) como último argumento toman un número variable de argumentos. C++ proporciona la comprobación de tipos solo para los argumentos declarados explícitamente. Puede usar listas de argumentos variables cuando el número y los tipos de argumentos de la función pueden variar. La printf familia de funciones es un ejemplo de funciones que tienen listas de argumentos variables.

Funciones con argumentos variables

Para acceder a los argumentos después de los declarados, use las macros contenidas en el archivo <stdarg.h> de inclusión estándar, como se explica en este artículo.

Específicos de Microsoft

Microsoft C++ permite especificar los puntos suspensivos como argumento si los puntos suspensivos son el último argumento y una coma viene antes de los puntos suspensivos. Por lo tanto, la declaración int Func( int i, ... ); es legal, pero int Func( int i ... ); no lo es.

FIN de Específicos de Microsoft

La declaración de una función que toma un número variable de argumentos requiere al menos un argumento de marcador de posición, incluso si no se usa. Si no se proporciona este argumento de marcador de posición, no hay ninguna manera de acceder a los argumentos restantes.

Cuando se pasan argumentos de tipo char como argumentos variables, se convierten en el tipo int. Del mismo modo, cuando los argumentos de tipo float se pasan como argumentos variables, se convierten en el tipo double. Los argumentos de otros tipos están sujetos a las promociones habituales de entero y de punto flotante. Para obtener más información, consulte Conversiones estándar.

Las funciones que requieren listas de variables se declaran con puntos suspensivos (...) en la lista de argumentos. Use los tipos y macros que se describen en el <stdarg.h> archivo de inclusión para tener acceso a los argumentos pasados por una lista de variables. Para obtener más información sobre estas macros, consulte va_arg, va_copy, va_end, va_start.

En el ejemplo siguiente se muestra cómo usar las macros para procesar una lista de argumentos de variable:

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

En el ejemplo anterior se muestran estos conceptos importantes:

  1. Debe establecer un marcador de lista como variable de tipo va_list antes de que se tenga acceso a cualquier argumento de variable. En el ejemplo anterior, el marcador se denomina vl.
  2. Se accede a los argumentos individuales mediante la macro va_arg. Debe indicar a la macro va_arg el tipo de argumento que debe recuperar para poder transferir el número correcto de bytes desde la pila. Si especifica un tipo incorrecto de un tamaño diferente del proporcionado por el programa de llamada a va_arg, los resultados son imprevisibles.
  3. Debe convertir explícitamente, mediante la macro va_arg, el resultado obtenido al tipo que desee.
  4. Debe llamar a la macro va_end para finalizar el procesamiento de argumentos variables.