È possibile utilizzare qualsiasi valore che si desidera contrassegnare la fine dell'elenco di argomenti, purché ne si sappia abbastanza sull'argomento dalla lista degli argomenti. Il compilatore normalmente non controlla che il valore scelto venga effettivamente passato quando viene chiamata la funzione, quindi è necessario averne cura.
Fondamentalmente si crea una funzione variadica nel solito modo, e all'interno della funzione si interrompe la lettura degli argomenti quando si legge uno che corrisponde alla sentinella - non c'è niente di particolarmente speciale da fare, ma è necessario sapere quali tipi di argomenti da leggere.
Ad esempio:
#include <stdarg.h>
/* Count arguments up to the number 5 */
int countArgsTilFive(int first, ...)
{
int res = 1;
va_list ap;
if (first == 5) return 0;
va_start(ap,first);
while (va_arg(ap,int) != 5) res++;
va_end(ap);
return res;
}
... conterà tutti i suoi argomenti che si verificano prima 5
. Le cose brutte potrebbero accadere se non lo passi a un numero 5
da qualche parte nella lista, comunque, o se gli passi argomenti che non sono int
.
Un altro esempio con i puntatori, in cui un linfonodo sentinella viene passato come il primo, e ancora una volta come ultimo argomento:
/* Count arguments, excluding the first, until the first occurs again */
int countPtrs(void *sentinel, ...)
{
int res = 0;
va_list ap;
va_start(ap,sentinel);
while (va_arg(ap,void *) != sentinel) res++;
va_end(ap);
return res;
}
Per quanto riguarda la creazione di tale funzione, è chiaramente possibile farlo. Non conosco alcuna estensione GNU per verificare che gli argomenti siano corretti per gli schemi arbitrari di vararg. Non hanno nemmeno un attributo per contrassegnare un parametro come un "conteggio" di quanti argomenti sono stati dati in modo che il compilatore possa verificare se è stato corretto. –