Funkce s proměnným počtem parametrů
proměnný počet parametrů se deklaruje pomocí tří teček jazyk C umožňuje programátorovi definovat vlastní funkce s proměnným počtem parametrů proměnný počet parametrů se deklaruje pomocí tří teček int maximum(n,…) povinné (pevné) parametry
funkci „musíme dát vědět“, kolik parametrů při konkrétním volání má, např. první parametr je povinný – počet parametrů jsou-li parametry číselné, stanovíme např., že poslední má hodnotu 0 aj. příklad: printf počet parametrů je dán počtem formátovacích specifikátorů % ve formátovacím řetězci
jak se dostaneme k dalším parametrům? parametry se v jazyce C ukládají na zásobník od posledního, tj. první parametr je na vrcholu zásobníku jak se dostaneme k dalším parametrům? přes ukazatele odvozené od adresy prvního parametru princip si ukážeme na funkci, která hledá maximum z n čísel; n je první povinný parametr funkce
Příklad funkce nesprávně napsané int maximum(int n,…) { int i; int max, hodn; int *prvy; prvy = &n+1; max = *prvy; for(i=1;i<n;i++) if ((hodn=*(prvy+i)) > max) max = hodn; return max; }
Co je na tom špatně? funkce bude pracovat správně pouze s čísly typu int a na procesorech Intel u procesorů Intel roste zásobník směrem dolů, tj. k parametrům pod vrcholem zásobníku přistoupím, přičítám-li hodnotu k ukazateli u jiných procesorů bych musel od ukazatele posuv odečítat řešení v knihovně stdarg.h jsou definována makra pro danou platformu
va_list je datový typ definovaný v knihovně void va_start(va_list ap, lastfix); type va_arg(va_list ap, type); void va_end(va_list ap); va_list je datový typ definovaný v knihovně ukazatel na void (vzdálený) va_start vrátí ukazatel na první nepovinný parametr, který následuje za posledním povinným poslední povinný je parametr makra lastfix ap je ukazatel na parametry typu va_list
va_arg vrací hodnotu aktuálního argumentu a posouvá ukazatel ap na další parametr va_end by mělo být voláno na konci funkce (implementačně závislé, např., nějaký „úklid“
Jak se to používá funkce deklaruje proměnnou typu va_list což je ukazatel voláním va_start jej inicializuje na hodnotu ukazující na první nepovinný parametr voláním va_arg vybírá cyklicky hodnotu jednotlivých parametrů zavolá makro va_end
int maximum(int n,…) { int i; int max, hodn; va_list ap; va_start(ap,n); max = va_arg(ap,int); for(i=1;i<n;i++) if ((hodn=va_arg(ap,int)) > max) max = hodn; va_end(ap); return max; }