next up previous contents
Elõre: Összetett mintapélda Fel: További magyarázatok Vissza: Még egyszer a deklarációkról

Függvények változó számú paraméterrel

A 1.10.2-es részben ismertetett printf, illetve scanf függvények (függvénycsaládok) tipikus példái a változó paraméterlistájú függvényeknek. A továbbiakban a printf függvény egy minimál implementációján keresztül mutatjuk be, hogyan készíthetünk portábilis, változó hosszúságú paraméterlistával rendelkezõ C függvényeket. Függvényünket a következõképpen deklaráljuk:

            void minprintf(const char *fmt, ...);
Azért void típusú a függvény, mert az egyszerûség kedvéért ebben a példában a konvertált adatok számával nem foglakozunk, így azt visszatérési értékül sem tudjuk szolgáltatni. A deklarációban a ... csak a formális paraméterlista utolsó elemeként szerepelhet, és legalább egy megnevezett argumentumot kell deklarálnunk ahhoz, hogy a változó hosszúságú paraméterlistát majd kezelni tudjuk.

A szabványos stdarg.h include file tartalmazza azokat a makrókat, amelyek a változó hosszúságú paraméterlisták kezeléséhez szükségesek. Az egyes makrók megvalósítása géprõl gépre változhat, de a makrók egységes felületet teremtenek a pobléma kezeléséhez.

A va_list típus szolgál arra, hogy a soronkövetkezõ függvényargumentumra vonatkozó információ tárolására való változót - egy argumentum-pointert - deklarálhassunk. A va_start( ) makróval inicializálhatunk egy ilyen változót. Az inicializálás eredményeképpen az argumentum-pointer az elsõ azonosító nélküli argumentumra fog mutatni. Mint említettük, legalább egy azonosítóval rendelkezõ elemet kell hogy tartalmazzon a formális paraméterlista. Ezt használja fel a va_start( ) makró az argumentum pointer inicializálásához. A va_arg( ) makróval léphetünk tovább a következõ azonosító nélküli argumentumra. Ez a makró a soron következõ aktuális paramétert szolgáltatja értékül. Ennek a makrónak két paramétere van. Az elsõ az argumentum-pointer, a második pedig egy típusazonosító, amely megszabja, hogy milyen legyen a visszatérési érték típusa, és hogy az argumentum-pointert milyen mértékben (hány byte-tal) kell továbbléptetni. A va_end( ) makró szolgál arra, hogy "rendet rakjon" egy változó hosszúságú paraméterlistával rendelkezõ függvénybõl való visszatérés elõtt. Ezt a makrót mindig meg kell hívni egy ilyen függvénybõl való kilépés alkalmával.

Ezek után nézzük meg az egyszerüsített printf függvény listáját!

#include <stdarg.h>
/************************************************************/
 void minprintf(const char *fmt, ...) 
/*                                                          */
/* Valtozo hosszusagu parameterlista kezelesenek bemutatasa */
/* a minimalis printf funkciok kapcsan. Mezoszelesseg, stb. */
/* kimarad, konverzio es nyomtatas az eredeti printf-fel.   */
/************************************************************/
{ va_list ap;        /* argumentum pointer                  */
  char    *p,        /* fmt-n szalad majd vegig             */
          *sval;     /* ->sztring tipusu parameter erteke   */
  int     ival;      /* int tipusu parameter erteke         */
  double  dval;      /* double tipusu parameter erteke      */
  
  va_start(ap, fmt); /* ap az fmt utani elso arg.-ra mutat  */
  for (p = fmt, *p, p++)            /* p-t EOS-ig lepteti   */
  { if (*p != '%') { putchar(*p); } /* Csak masolas         */
    else             /* specifikacio feldolgozasa:          */
    { switch(*++p)   
      { 
        case 'd': ival = va_arg(ap, int);
                  printf("%d", ival);
                  break;

        case 'f': dval = va_arg(ap, double);
                  printf("%f", dval);
                  break;
        
        case 's': for(sval = va_arg(ap,char*); *sval; sval++)
                  {
                    putchar(*sval);
                  }
                  break;
         
        default:  putchar(*p);
                  break;
      }
    }
  }
  va_end(ap); /* Takaritas a fuggveny vegen                 */
}      
/************************************************************/