Bagikan melalui


Fungsi dengan Daftar Argumen Variabel (C++)

Deklarasi fungsi yang memiliki elipsis (...) sebagai argumen terakhir mengambil jumlah variabel argumen. C++ menyediakan pemeriksaan jenis hanya untuk argumen yang dideklarasikan secara eksplisit. Anda dapat menggunakan daftar argumen variabel saat jumlah dan jenis argumen ke fungsi dapat bervariasi. Keluarga printf fungsi adalah contoh fungsi yang memiliki daftar argumen variabel.

Fungsi dengan argumen variabel

Untuk mengakses argumen setelah dinyatakan, gunakan makro yang terkandung dalam standar sertakan file <stdarg.h> seperti yang dijelaskan dalam artikel ini.

Khusus Microsoft

Microsoft C++ memungkinkan elipsis ditentukan sebagai argumen jika elipsis adalah argumen terakhir dan koma datang sebelum elipsis. Oleh karena itu, deklarasi int Func( int i, ... ); itu legal, tetapi int Func( int i ... ); tidak.

END Khusus Microsoft

Deklarasi fungsi yang mengambil jumlah variabel argumen memerlukan setidaknya satu argumen tempat penampung, meskipun tidak digunakan. Jika argumen placeholder ini tidak disediakan, tidak ada cara untuk mengakses argumen yang tersisa.

Ketika argumen jenis char diteruskan sebagai argumen variabel, argumen tersebut dikonversi ke jenis int. Demikian pula, ketika argumen jenis float diteruskan sebagai argumen variabel, argumen tersebut dikonversi ke jenis double. Argumen jenis lain tunduk pada promosi integral dan floating-point yang biasa. Untuk informasi selengkapnya, lihat Konversi Standar.

Fungsi yang memerlukan daftar variabel dideklarasikan dengan menggunakan elipsis (...) dalam daftar argumen. Gunakan jenis dan makro yang dijelaskan dalam file penyertaan <stdarg.h> untuk mengakses argumen yang diteruskan melalui daftar variabel. Untuk informasi selengkapnya tentang makro ini, lihat va_arg, va_copy, va_end, va_start.

Contoh berikut menunjukkan cara menggunakan makro untuk memproses daftar argumen variabel:

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

Contoh sebelumnya mengilustrasikan konsep-konsep penting ini:

  1. Anda harus membuat penanda daftar sebagai variabel jenis va_list sebelum argumen variabel apa pun diakses. Dalam contoh sebelumnya, penanda disebut vl.
  2. Argumen individual diakses dengan menggunakan va_arg makro. Anda harus memberi tahu va_arg makro tipe argumen untuk diambil sehingga dapat mentransfer jumlah byte yang benar dari tumpukan. Jika Anda menentukan jenis ukuran yang salah yang berbeda dari yang disediakan oleh program panggilan ke va_arg, hasilnya tidak dapat diprediksi.
  3. Anda harus secara eksplisit mentransmisikan hasil yang diperoleh dengan menggunakan va_arg makro ke jenis yang Anda inginkan.
  4. Anda harus memanggil va_end makro untuk mengakhiri pemrosesan argumen variabel.