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_arg
Makro , 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_start
arg_ptr
diatur ke argumen opsional pertama dalam daftar argumen yang diteruskan ke fungsi. Argumenarg_ptr
harus memiliki jenis .va_list
Argumenprev_param
adalah nama parameter yang diperlukan yang segera mendahului argumen opsional pertama dalam daftar argumen. Jikaprev_param
dideklarasikan dengan kelas penyimpanan register, perilaku makro tidak ditentukan.va_start
harus digunakan sebelumva_arg
digunakan untuk pertama kalinya.va_arg
mengambil nilai daritype
lokasi yang diberikan oleharg_ptr
, dan kenaikanarg_ptr
untuk menunjuk ke argumen berikutnya dalam daftar dengan menggunakan ukurantype
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. Parametersrc
harus sudah diinisialisasi denganva_start
; mungkin telah diperbarui denganva_arg
panggilan, tetapi tidak boleh diatur ulang denganva_end
. Argumen berikutnya yang diambil oleh dari sama denganva_arg
argumen berikutnya yang diambil darisrc
.dest
Setelah semua argumen diambil,
va_end
reset pointer keNULL
.va_end
harus dipanggil pada setiap daftar argumen yang diinisialisasi denganva_start
atauva_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 int
char*
. Argumen yang diteruskan 0xffffffff ( unsigned int
, bukan int
) dan NULL
(sebenarnya , int
bukan 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