Udostępnij za pośrednictwem


Funkcje z listami zmiennych argumentów (C++)

Deklaracje funkcji z wielokropkiem (...) jako ostatni argument przyjmują zmienną liczbę argumentów. Język C++ zapewnia sprawdzanie typów tylko dla jawnie zadeklarowanych argumentów. Można użyć list argumentów zmiennych, gdy liczba i typy argumentów funkcji mogą się różnić. printf Rodzina funkcji jest przykładem funkcji, które mają listy argumentów zmiennych.

Funkcje z argumentami zmiennych

Aby uzyskać dostęp do argumentów po tych zadeklarowanych, użyj makr zawartych w standardowym pliku nagłówkowym <stdarg.h>, jak wyjaśniono w tym artykule.

Specyficzne dla firmy Microsoft

Język Microsoft C++ umożliwia określenie wielokropka jako argumentu, jeśli wielokropek jest ostatnim argumentem, a przecinek pojawia się przed wielokropkiem. W związku z tym deklaracja int Func( int i, ... ); jest legalna, ale int Func( int i ... ); nie jest.

Koniec specyfiki Microsoftu

Deklaracja funkcji, która przyjmuje zmienną liczbę argumentów, wymaga co najmniej jednego argumentu zastępczego, nawet jeśli nie jest używana. Jeśli ten argument zastępczy nie zostanie podany, nie ma możliwości uzyskania dostępu do pozostałych argumentów.

Gdy argumenty typu char są przekazywane jako argumenty zmiennych, są konwertowane na typ int. Podobnie, gdy argumenty typu float są przekazywane jako argumenty zmiennych, są konwertowane na typ double. Argumenty innych typów podlegają zwykłym promocji całkowitych i zmiennoprzecinkowych. Aby uzyskać więcej informacji, zobacz Konwersje standardowe.

Funkcje wymagające list zmiennych są deklarowane przy użyciu wielokropka (...) na liście argumentów. Użyj typów i makr opisanych w <stdarg.h> pliku dołączania, aby uzyskać dostęp do argumentów przekazywanych przez listę zmiennych. Aby uzyskać więcej informacji na temat tych makr, zobacz va_arg, va_copy, va_end, va_start.

W poniższym przykładzie pokazano, jak używać makr do przetwarzania listy argumentów zmiennych:

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

W poprzednim przykładzie przedstawiono następujące ważne pojęcia:

  1. Przed uzyskaniem dostępu do argumentów zmiennych należy ustanowić znacznik listy jako zmienną typu va_list . W poprzednim przykładzie znacznik nosi nazwę vl.
  2. Dostęp do poszczególnych argumentów uzyskuje się przy użyciu makra va_arg . Należy poinformować va_arg makro o typie argumentu do pobrania, aby można było przenieść prawidłową liczbę bajtów ze stosu. Jeśli określisz nieprawidłowy typ rozmiaru innego niż podany przez program wywołujący do va_argprogramu , wyniki są nieprzewidywalne.
  3. Należy jawnie rzutować wynik uzyskany przy użyciu makra va_arg do żądanego typu.
  4. Aby zakończyć przetwarzanie argumentów zmiennych, należy wywołać va_end makro.