Yerleşik biçimli çıktı işlevleri olarak printf oluşumunu kullanarak kendi değişkin printf benzeri işlevlerinizi tanımlayabilmeniz için vprintf işlevi ve arkadaşları oluşturulmuştur.
Bu tür işlevleri tanımlamanın en doğal yolu, "printf işlevini çağır ve bu şablonla birlikte ilk 5 argümandan sonra benim argümanlarımı aktar" diyecek bir dil yapısı kullanmak olurdu. Fakat C'de bunu yapmanın bir yolu yoktur. Ayrıca üçüncü düzey C dilinde işlevinizin kaç argüman aldığını söyleyecek bir yol olmadığından, bir yol üretmek de zor olurdu.
Bu yöntemle mümkün olmadığından "ilk 5 argümandan sonra benim argümanlarımı aktar" diyebileceğiniz bir va_list'i aktaracağınız bir seri işlev, vprintf serisini ürettik.
Gerçek bir işlev yerine bir makro tanımlamak yeterli olduğundan, GNU C derleyicisi bunu makrolarla çok daha kolay yapacak bir yol sağlar. Örneğin:
#define myprintf(a, b, c, d, e, rest...) \
printf (mytemplate , ## rest)
Değişken sayıda argümanlı makrolar hakkında ayrıntılı bilgi edinmek için GCC info'sundaki "Macros with Variable Numbers of Arguments" (Değişken sayıda argümanlı makrolar) bölümüne bakınız. Bu yol sadece makrolara ayrılmıştır, gerçek işlevlere uygulanmaz.
vprintf veya bu bölümde listelenmiş diğer işlevleri çağırmadan önce değişken sayıdaki argümanı ilklendirmek için bir
va_start çağrısı (
Değişkin İşlevler) yapmalısınız. Sonra da kendinizin elde etmek istediğiniz argümanları almak için
va_arg çağrıları yapmalısınız.
va_list göstericinize seçtiğiniz ilk argümanı gösterdikten sonra bir vprintf çağrısı yapmaya hazırsınız demektir. İşlevinizle aktardığınız bu argüman ve artbileşen argümanlar ile belirttiğiniz şablon dizgesi vprintf işlevi tarafından kullanılacaktır.
Diğer sistemlerde vprintf çağrısından sonra va_list göstericisi geçersiz duruma gelebilir ve vprintf çağrısından sonra va_arg işlevini kullanamayabilirsiniz. Bu durumda bir va_end çağrısından sonra va_start ile göstericiyi yeniden almalısınız. vprintf işlevi işlevinizin argüman listesini ortadan kaldırmaz.
GNU C böyle sınırlamalara sahip değildir. va_list göstericisini vprintf çağrısına aktardıktan sonra bu göstericiyi kullanarak argümanları almaya devam edebilirsiniz ve va_end çağrısı da hiçbir işlem yapmaz. (vprintf çağrısından sonra yaptığınız va_arg çağrıları ile alınan argümanlar vprintf çağrısındaki argümanlarla aynıdır.)
Bu işlevlerin prototipleri
stdio.h başlık dosyasında bildirilmiştir.
int vprintf | (const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında printf ile aynıdır.
int vwprintf | (const wchar_t *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında wprintf ile aynıdır.
int vfprintf | (FILE *akım,
const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında vprintf ile aynıdır.
int vfwprintf | (FILE *akım,
const wchar_t *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında vwprintf ile aynıdır.
int vsprintf | (char *s,
const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında sprintf ile aynıdır.
int vswprintf | (wchar_t *s,
size_t boyut,
const wchar_t *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında swrintf ile aynıdır.
int vsnprintf | (char *s,
size_t boyut,
const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında snprintf ile aynıdır.
int vasprintf | (char **gstr,
const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında vasprintf ile aynıdır.
int obstack_vprintf | (struct obstack *yığınak,
const char *şablon,
va_list arglist-gstr) |
işlev
Bu işlev değişken sayıdaki argümanlarını doğrudan almak yerine arglist-gstr argüman listesi göstericisinden alması dışında obstack_vprintf ile aynıdır.
Aşağıda
vfprintf kullanılan bir örnek vardır. Örnekteki işlev yazılımın ismi ile önceleyerek standart hataya bir ileti basmaktadır. (
program_invocation_short_name değişkeninin açıklamaları için
Hata İletileri bölümüne bakınız.)
#include <stdio.h>
#include <stdarg.h>
void
eprintf (const char *sablon, ...)
{
va_list ap;
extern char *program_invocation_short_name;
fprintf (stderr, "%s: ", program_invocation_short_name);
va_start (ap, sablon);
vfprintf (stderr, sablon, ap);
va_end (ap);
}
eprintf işlevi şöyle çağrılabilir:
eprintf ("`%s' diye bir dosya yok\n", filename);
GNU C'de printf tarzı biçim dizgesi kullanan bir işlevi derleyiciye bildirebileceğiniz özel bir yapı vardır. Bu yapı kullanıldığında işlevin her çağrısı için kullanılan argümanların türleri ve sayısı denetlenir ve biçim dizgesiyle eşleşmeyenler için sizi uyarır. Örneğin, bu yapıyı eprintf için şöyle kullanabilirsiniz:
void eprintf (const char *sablon, ...)
__attribute__ ((format (printf, 1, 2)));
Bu kod parçası derleyiciye eprintf işlevinin ilk argümanının printf biçim dizgesi olarak, biçim dizgesini oluşturan diğer argümanların başlangıcının ikinci argüman olarak kullanıldığını söyler. İşlev özniteliklerinin bildirilmesi ile ilgili ayrıntılı bilgi edinmek için GCC kılavuzunun (info) "Declaring Attributes of Functions" (İşlevlerin Özniteliklerinin Bildirilmesi) bölümüne bakınız.