Dosud jsme definovali jen funkce s pevným počtem parametrů.
Používali jsme ale i funkce které měli proměnlivý počet parametrů a to funkci
printf
, které jsme předávali formátovací řetězec a libovolný počet argumenů.
Víme že hodnoty parametrů funkcí se ukladají na zásobník. Tyto hodnoty jsou v paměti tedy uloženy za sebou. Pokud tedy známe adresu a velikost datového typu jsme schopni se přesunout na další parametr.
Funkce s proměnným počtem parametrů musí mít alespoň jeden pevný parametr a musí být zadán počet parametrů které následují. Prvním způsobem jak toho docilít je předat počet ja pevný parametr a nebo použít zarážku. Poslední informací jsou datové typ těchto parametrů. Tyto informace můžeme předat následovně:
- Počet argumentů a jejich typy předány formátovacím řetězcem (např.
printf
). - Předpokládáme typ parametrů a funkci je předán jejich počet (např. suma, průměr).
- předpokládáme typ parametrů a máme určenou zarážku (např. práce s řetězci).
Deklarace
Pro delklaraci proměnného počtu parametrů používáme ...
int sum(size_t count, ...) {
// Implementace funkce
}
int a = sum(4, 8, 9, 14, 57);
// V jazyce C NEMUZEME sum definovat nasledovne
int sum(...) { /* Implementace funkce */ }
Zpracování parametrů v těle funkce
V knihovně stdarg.h
jsou definována makra pro práci s parametry:
va_list
, va_start
, va_arg
, va_end
kde:
va_list
je datový typ pro uložení odkazu na parametry.va_start
inicializuje proměnnouva_list
.va_arg
čte další parametr.va_end
ukončuje práci s parametry.
Příklad použití
#include <stdio .h>
#include <stdarg.h>
double average(int count, ...) {
// V tele funkce musime deklarovat alespon
// jednu promennou typu va_list
va_list parameters;
// Nastavime parameters na prvni nepovinny parametr
va_start(parameters, count);
double sum = 0;
for(int i = 0; i < count; i += 1) {
// Ziskame hodnotu nepovinneho parametru
sum = sum + va_arg(parameters, double);
}
// Ukoncime praci s parametry
va_end(parameters);
return sum / count;
}
int main() {
printf ("%f \n" , average(5 , 1.2 , 3.4 , 5.6 , 7.8 , 9.0));
return 0;
}