Stdarg.h - Stdarg.h

stdarg.h sarlavhasi C standart kutubxonasi ning C dasturlash tili funktsiyalarni qabul qilishga imkon beradi noaniq miqdordagi argumentlar.[1] Bu raqam va turdagi noma'lum funktsiyalar argumentlari ro'yxati orqali o'tish uchun qulayliklar yaratadi. C ++ sarlavhada ushbu funktsiyani ta'minlaydi cstdarg.

Ning mazmuni stdarg.h odatda ichida ishlatiladi o'zgaruvchan funktsiyalar ammo ular boshqa funktsiyalarda ishlatilishi mumkin (masalan, vprintf) variadik funktsiyalar bilan chaqiriladi.

Turli xil funktsiyalarni e'lon qilish

Turli xil funktsiyalar o'zgaruvchan sonli argumentlarni qabul qilishi va an bilan e'lon qilingan funktsiyalardir ellipsis oxirgi parametr o'rniga. Bunday funktsiyaga misol printf. Odatda deklaratsiya

int tekshirish(int a, ikki baravar b, ...);

Turli xil funktsiyalar kamida bitta nomlangan parametrga ega bo'lishi kerak, shuning uchun, masalan,

char *noto'g'ri(...);

C da ruxsat berilmaydi (C ++ da bunday deklaratsiyaga ruxsat beriladi.) C da ellipsis oldida vergul bo'lishi kerak; C ++ da bu ixtiyoriy.

Turli xil funktsiyalarni aniqlash

Xuddi shu sintaksis ta'rifida ishlatiladi:

uzoq funktsiya(char, ikki baravar, int, ...);uzoq funktsiya(char a, ikki baravar b, int v, ...){    /* ... */}

Eski uslubdagi funktsiyalar ta'riflarida ellipsis ko'rinmasligi mumkin.

stdarg.h turlari

IsmTavsifMoslik
va_listargumentlarni takrorlash uchun yozingC89

stdarg.h makrolari

IsmTavsifmoslik
va_startArgumentlarni takrorlashni a bilan boshlang va_listC89
va_argDalilni olingC89
va_endBepul a va_listC89
va_copyBirining tarkibini nusxalash va_list boshqasigaC99

Dalillarga kirish

Noma'lum dalillarga kirish uchun turdagi o'zgaruvchini e'lon qilish kerak va_list variadic funktsiyasida. Ibratli va_start keyin ikkita argument bilan chaqiriladi: birinchisi - bu turdagi e'lon qilingan o'zgaruvchi va_list, ikkinchisi - funktsiyaning oxirgi nomlangan parametrining nomi. Shundan so'ng, har bir chaqiruv va_arg so'l keyingi argumentni beradi. Birinchi argument va_arg bo'ladi va_list ikkinchisi esa funktsiyaga o'tgan keyingi argument turi. Va nihoyat va_end so'l chaqirilishi kerak va_list funktsiya qaytmasidan oldin. (Barcha argumentlarda o'qish shart emas.)

C99 qo'shimcha so'lni taqdim etadi, va_copy, a holatini takrorlashi mumkin va_list. Ibratli chaqiruv va_copy (va2, va1) nusxalari va1 ichiga va2.

Funktsiyaga berilgan noma'lum argumentlarning sonini yoki turlarini aniqlash mexanizmi aniqlanmagan. Buning vazifasi shunchaki vositasi turlicha bo'lganligini bilish yoki aniqlash uchun talab qilinadi. Umumiy konvensiyalarga quyidagilar kiradi:

  • A dan foydalanish printf yoki skanf- argument turlarini ko'rsatadigan ko'milgan spetsifikatorlarga ega format qatori.
  • A qo'riqchi qiymati variadik argumentlar oxirida.
  • Turli xil argumentlar sonini ko'rsatadigan hisoblash argumenti.

Boshqa qo'ng'iroqlarga noma'lum dalillarni etkazish

Noma'lum argumentlar ro'yxati odatda noma'lum bo'lganligi sababli (ko'pgina kompilyatorlar tomonidan qo'llaniladigan chaqiruv konventsiyalari nomlangan argumentlar blokining hajmini belgilashga imkon bermaydi va_list qabul qiluvchi funktsiya ichida), noma'lum argumentlarni boshqa variadik funktsiyaga yo'naltirishning ishonchli, umumiy usuli ham mavjud emas. Argumentlar ro'yxati hajmini bilvosita usullar bilan aniqlash mumkin bo'lgan joyda ham (masalan, formatining satrini ajratish orqali) fprintf ()), dinamik ravishda aniqlangan argumentlar sonini ichki variadik chaqiruvga o'tkazishning ko'chma usuli yo'q, chunki bunday qo'ng'iroqlarga berilgan argumentlar soni va hajmi odatda kompilyatsiya vaqtida ma'lum bo'lishi kerak. Muayyan darajada, ushbu cheklovni ish bilan ta'minlash orqali yumshatish mumkin turli xil makrolar variadik funktsiyalar o'rniga. Bundan tashqari, ko'pgina standart kutubxona protseduralari ta'minlanadi v- oldindan qabul qilingan muqobil versiyalar ma'lumotnoma noma'lum argumentlar ro'yxatiga (ya'ni boshlangan va_list nomlanmagan argumentlar ro'yxati o'rniga. Masalan, vfprintf () ning muqobil versiyasidir fprintf () kutish a va_list haqiqiy nomlanmagan argumentlar ro'yxati o'rniga. Shuning uchun foydalanuvchi tomonidan belgilangan variadik funktsiya a ni ishga tushirishi mumkin va_list o'zgaruvchan va_start va uni tegishli standart kutubxona funktsiyasiga o'tkazing, aslida nomi bilan nomlanmagan argumentlar ro'yxatini qiymat bo'yicha bajarish o'rniga havola orqali o'tkazing. Chunki nomlanmagan argumentlar ro'yxatini C qiymatida, variadic bilan ta'minlashning ishonchli usuli yo'q API teng funktsiyalarni qabul qilmasdan ham funktsiyalar va_list o'rniga yomon dasturlash amaliyoti hisoblanadi.

Xavfsizlik turi

Ba'zi bir C dasturlari kompilyatorga format satrlari va qo'riqchilaridan to'g'ri foydalanilishini tekshirishga imkon beradigan C kengaytmalarini taqdim etadi. Ushbu kengaytmalarni taqiqlash, kompilyator odatda noma'lum argumentlarni funktsiya kutgan turdagi ekanligini tekshira olmaydi yoki ularni kerakli turga o'zgartira olmaydi. Shuning uchun, bu borada to'g'riligini ta'minlash uchun ehtiyot bo'lish kerak, chunki aniqlanmagan xatti-harakatlar turlari mos kelmasa natijalar. Masalan, kutilgan tur bo'lsa int *, keyin bo'sh ko'rsatgich sifatida uzatilishi kerak (int *) NULL. Faqat yozish NULL ham turdagi tortishuvlarga olib keladi int yoki bekor *, ikkalasi ham to'g'ri emas. Boshqa mulohaza - bu standart dalil aktsiyalar noma'lum dalillarga nisbatan qo'llaniladi. A suzmoq avtomatik ravishda a ga ko'tariladi ikki baravar. Xuddi shunday, turlarning argumentlari an dan torroq int lavozimiga ko'tariladi int yoki unsigned int. Noma'lum argumentlarni qabul qiluvchi funktsiya ilgari surilgan turni kutishi kerak.

GCC o'tgan argumentlarni tekshiradigan kengaytmaga ega:

format (arxetip, string-index, birinchi tekshirish)

Format atributi funktsiya bajarilishini belgilaydi printf, skanf, vaqtinchalik yoki strfmon format argumentlari, ular format qatoriga qarab tekshirilishi kerak. Masalan, deklaratsiya:

tashqi intmy_printf (bekor *my_object, konst char *my_format, ...)      __xususiyat__ ((format (printf, 2, 3)));

qo'ng'iroqlaridagi kompilyatorning argumentlarni tekshirishiga sabab bo'ladi my_printf ga muvofiqligi uchun printf uslubi formatidagi argument my_format.

— "5.27 C tilidagi oilaga kengaytmalar - funktsiyalarning xususiyatlarini e'lon qilish". Olingan 2009-01-03.

Misol

# shu jumladan <stdio.h># shu jumladan <stdarg.h>/ * barcha argumentlarni birma-bir salbiy argument ko'rinmaguncha chop eting;   barcha arglar int tipidagi * / deb qabul qilinadibekor printerlar(int arg1, ...){  va_list ap;  int men;  va_start(ap, arg1);   uchun (men = arg1; men >= 0; men = va_arg(ap, int))    printf("% d", men);  va_end(ap);  putchar(' n');}int asosiy(bekor){   printerlar(5, 2, 14, 84, 97, 15, -1, 48, -1);   printerlar(84, 51, -1, 3);   printerlar(-1);   printerlar(1, -1);   qaytish 0;}

Ushbu dastur natijani beradi:

5 2 14 84 97 1584 511

Sizning funktsiyangiz ichidagi boshqa var args funktsiyalarini chaqirish uchun (masalan, sprintf) funktsiya var arg versiyasidan foydalanishingiz kerak (vsprintf ushbu misolda):

bekor MyPrintf(konst char *format, ...){  va_list kamon;  char bufer[BUFSIZ];  va_start(kamon, format);  vsnprintf(bufer, o'lchamlari bufer, format, kamon);  va_end(kamon);  FlushFunnyStream(bufer);}

varargs.h

Ning eskirgan versiyalari POSIX meros sarlavhasini aniqladi varargs.h, bu C standartlashtirilishidan oldingi va shunga o'xshash funksiyalarni ta'minlaydigan stdarg.h. Ushbu sarlavha na ISO C, na POSIX-ning bir qismi emas. Ikkinchi versiyasida aniqlangan fayl Yagona UNIX spetsifikatsiyasi, shunchaki C89 ning barcha funktsiyalarini o'z ichiga oladi stdarg.h, istisnolardan tashqari: uni standart C yangi uslubidagi ta'riflarda ishlatish mumkin emas; siz berilgan argumentga ega bo'lmaslikni tanlashingiz mumkin (standart C kamida bitta argumentni talab qiladi); va ishlash usuli boshqacha - C standartida quyidagilar yoziladi:

# shu jumladan <stdarg.h>int yig'moq(int n, ...){    va_list ap;    int men = 0;    va_start(ap, n);    uchun (; n; n--)        men += va_arg(ap, int);    va_end(ap);    qaytish men;}

va bilan qo'ng'iroq qiling

yig'moq(0);yig'moq(1, 2);yig'moq(4, 9, 2, 3, 2);

Bilan varargs.h, funktsiya quyidagicha bo'ladi:

# shu jumladan <varargs.h>yig'moq(n, va_alist)    va_dcl / * bu erda nuqta-vergul yo'q! * /{    va_list ap;    int men = 0;    va_start(ap);    uchun (; n; n--)        men += va_arg(ap, int);    va_end(ap);    qaytish men;}

va xuddi shu tarzda chaqiriladi.

varargs.h amalga oshirish uslubi tufayli eski uslubdagi funktsiya ta'riflarini talab qiladi.[2] Aksincha, eski uslubdagi funktsiya ta'riflarini aralashtirish mumkin emas stdarg.h.

Adabiyotlar