Bagikan melalui


va_arg, va_copy, va_end, va_start

Mengakses daftar argumen variabel.

Sintaks

type va_arg(
   va_list arg_ptr,
   type
);
void va_copy(
   va_list dest,
   va_list src
); // (ISO C99 and later)
void va_end(
   va_list arg_ptr
);
void va_start(
   va_list arg_ptr,
   prev_param
); // (ANSI C89 and later)
void va_start(
   arg_ptr
);  // (deprecated Pre-ANSI C89 standardization version)

Parameter

type
Jenis argumen yang akan diambil.

arg_ptr
Penunjuk ke daftar argumen.

dest
Penunjuk ke daftar argumen yang akan diinisialisasi dari src

src
Penunjuk ke daftar argumen yang diinisialisasi untuk disalin ke dest.

prev_param
Parameter yang mendahului argumen opsional pertama.

Nilai hasil

va_arg mengembalikan argumen saat ini. va_copy, va_start dan va_end jangan mengembalikan nilai.

Keterangan

va_argMakro , va_copy, va_end, dan va_start menyediakan cara portabel untuk mengakses argumen ke fungsi ketika fungsi mengambil jumlah variabel argumen. Ada dua versi makro: Makro yang ditentukan STDARG.H sesuai dengan standar ISO C99; makro yang ditentukan tidak VARARGS.H digunakan lagi tetapi dipertahankan untuk kompatibilitas mundur dengan kode yang ditulis sebelum standar ANSI C89.

Makro ini mengasumsikan bahwa fungsi mengambil sejumlah argumen yang diperlukan tetap, diikuti dengan jumlah variabel argumen opsional. Argumen yang diperlukan dinyatakan sebagai parameter biasa ke fungsi dan dapat diakses melalui nama parameter. Argumen opsional diakses melalui makro di STDARG.H (atau VARARGS.H untuk kode yang ditulis sebelum standar ANSI C89), yang mengatur penunjuk ke argumen opsional pertama dalam daftar argumen, mengambil argumen dari daftar, dan mengatur ulang penunjuk saat pemrosesan argumen selesai.

Makro standar C, yang didefinisikan dalam STDARG.H, digunakan sebagai berikut:

  • va_startarg_ptr diatur ke argumen opsional pertama dalam daftar argumen yang diteruskan ke fungsi. Argumen arg_ptr harus memiliki jenis .va_list Argumen prev_param adalah nama parameter yang diperlukan yang segera mendahului argumen opsional pertama dalam daftar argumen. Jika prev_param dideklarasikan dengan kelas penyimpanan register, perilaku makro tidak ditentukan. va_start harus digunakan sebelum va_arg digunakan untuk pertama kalinya.

  • va_arg mengambil nilai dari type lokasi yang diberikan oleh arg_ptr, dan kenaikan arg_ptr untuk menunjuk ke argumen berikutnya dalam daftar dengan menggunakan ukuran type untuk menentukan di mana argumen berikutnya dimulai. va_arg dapat digunakan berapa kali dalam fungsi untuk mengambil argumen dari daftar.

  • va_copy membuat salinan daftar argumen dalam statusnya saat ini. Parameter src harus sudah diinisialisasi dengan va_start; mungkin telah diperbarui dengan va_arg panggilan, tetapi tidak boleh diatur ulang dengan va_end. Argumen berikutnya yang diambil oleh dari sama dengan va_arg argumen berikutnya yang diambil dari src.dest

  • Setelah semua argumen diambil, va_end reset pointer ke NULL. va_end harus dipanggil pada setiap daftar argumen yang diinisialisasi dengan va_start atau va_copy sebelum fungsi kembali.

Catatan

Makro di VARARGS. H tidak digunakan lagi dan hanya dipertahankan untuk kompatibilitas mundur dengan kode yang ditulis sebelum standar ANSI C89. Dalam semua kasus lain, gunakan makro di STDARGS.H.

Ketika dikompilasi dengan menggunakan /clr (Common Language Runtime Compilation), program yang menggunakan makro ini dapat menghasilkan hasil yang tidak terduga karena perbedaan antara sistem jenis runtime bahasa asli dan bahasa umum (CLR). Pertimbangkan program ini:

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

void testit (int i, ...)
{
    va_list argptr;
    va_start(argptr, i);

    if (i == 0)
    {
        int n = va_arg(argptr, int);
        printf("%d\n", n);
    }
    else
    {
        char *s = va_arg(argptr, char*);
        printf("%s\n", s);
    }

    va_end(argptr);
}

int main()
{
    testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
    testit(1, NULL);       // 2nd problem: NULL is not a char*
}

Perhatikan bahwa testit mengharapkan parameter kedua menjadi atau intchar*. Argumen yang diteruskan 0xffffffff ( unsigned int, bukan int) dan NULL (sebenarnya , intbukan char*). Ketika program dikompilasi untuk kode asli, program menghasilkan output ini:

-1

(null)

Persyaratan

Header:<stdio.h> dan <stdarg.h>

Header tidak digunakan lagi:<varargs.h>

Pustaka

Semua versi pustaka run-time C.

Contoh

// crt_va.c
// Compile with: cl /W3 /Tc crt_va.c
// The program below illustrates passing a variable
// number of arguments using the following macros:
//      va_start            va_arg              va_copy
//      va_end              va_list

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

double deviation(int first, ...);

int main( void )
{
    /* Call with 3 integers (-1 is used as terminator). */
    printf("Deviation is: %f\n", deviation(2, 3, 4, -1 ));

    /* Call with 4 integers. */
    printf("Deviation is: %f\n", deviation(5, 7, 9, 11, -1));

    /* Call with just -1 terminator. */
    printf("Deviation is: %f\n", deviation(-1));
}

/* Returns the standard deviation of a variable list of integers. */
double deviation(int first, ...)
{
    int count = 0, i = first;
    double mean = 0.0, sum = 0.0;
    va_list marker;
    va_list copy;

    va_start(marker, first);     /* Initialize variable arguments. */
    va_copy(copy, marker);       /* Copy list for the second pass */
    while (i != -1)
    {
        sum += i;
        count++;
        i = va_arg(marker, int);
    }
    va_end(marker);              /* Reset variable argument list. */
    mean = sum ? (sum / count) : 0.0;

    i = first;                  /* reset to calculate deviation */
    sum = 0.0;
    while (i != -1)
    {
        sum += (i - mean)*(i - mean);
        i = va_arg(copy, int);
    }
    va_end(copy);               /* Reset copy of argument list. */
    return count ? sqrt(sum / count) : 0.0;
}
Deviation is: 0.816497
Deviation is: 2.236068
Deviation is: 0.000000

Baca juga

Akses argumen
vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l