[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 596.   C: «stdarg.h»

Il file stdarg.h della libreria standard definisce principalmente delle macro-istruzioni per gestire gli argomenti variabili passati a una funzione, assieme a un tipo di variabile, va_list, specifico per gestire il puntatore a tali parametri non dichiarati.

Tabella 596.1. Macro-istruzioni standard per la gestione di argomenti variabili.

Macro-istruzione Descrizione
void va_start (va_list ap, parametro_n);
Inizializza la variabile ap, di tipo va_list, in modo che punti all'area di memoria immediatamente successiva al parametro indicato, il quale deve essere l'ultimo.
tipo va_arg (va_list ap, tipo);
Restituisce il contenuto dell'area di memoria a cui punta ap, utilizzando il tipo indicato, incrementando contestualmente il puntatore in modo che, al termine, si trovi nell'area di memoria immediatamente successiva.
void va_copy (va_list dst, va_list org);
Copia il puntatore org nella variabile dst.
void va_end (va_list ap);
Conclude l'utilizzo del puntatore ap.

596.1   Realizzazione

Il listato successivo è tutto ciò che serve per realizzare la libreria:

typedef unsigned char * va_list;

#define va_start(AP, LAST) \
    ((void) ((AP) = ((va_list) &(LAST)) + (sizeof (LAST))))

#define va_end(AP) ((void) ((AP) = 0))
#define va_copy(DEST, SRC) ((void) ((DEST) = (va_list) (SRC)))

#define va_arg(AP, TYPE) (((AP) = (AP) + (sizeof (TYPE))), \
                          *((TYPE *) ((AP) - (sizeof (TYPE)))))

Delle macro-istruzioni mostrate nell'esempio, la più difficile da interpretare potrebbe essere va_arg, la quale deve restituire il valore dell'area di memoria puntata inizialmente, ma garantendo di lasciare il puntatore pronto per l'area successiva. In pratica, prima viene incrementato il puntatore per l'area successiva, quindi viene dereferenziato ricalcolando lo spazio necessario a raggiungere la posizione precedente. In altri termini è come scrivere:

...
va_list ap;
...
//
// va_start
//
ap = (va_list) &ultimo_parametro;
ap = ap + (sizeof (tipo_ultimo_parametro);
...
//
// va_arg
//
ap = ap + (sizeof tipo_successivo);
var = (tipo_successivo *) (ap - (sizeof (tipo_successivo)));
...
//
// va_end
//
ap = 0;
...

596.2   Esempio di utilizzo delle macro

Viene riproposto un programma molto semplice, già apparso in altri capitoli, per dimostrare l'utilizzo delle macro-istruzioni dichiarate nel file stdarg.h.

#include <stdio.h>
#include <stdarg.h>

void
f (int w,...)
{
    long double x;      // Dichiara le variabili che servono
    long long int y;    // a contenere gli argomenti per i
    int z;              // quali mancano i parametri formali.

    va_list ap;         // Dichiara il puntatore agli argomenti.

    va_start (ap, w);   // Posiziona il puntatore dopo la fine di «w».

    x = va_arg (ap, long double);       // Estrae l'argomento successivo
                                        // portando avanti il puntatore
                                        // di conseguenza.

    printf ("w = %d; ", w);     // Mostra il valore del primo parametro.
    printf ("x = %Lf; ", x);    // Mostra il valore dell'argomento successivo.

    y = va_arg (ap, long long int);     // Estrapola e mostra
    printf ("y = %lld; ", y);           // il terzo argomento.

    z = va_arg (ap, int);               // Estrapola e mostra
    printf ("z = %d\n", z);             // il quarto argomento.

    va_end (ap);                        // Conclude la scansione.

    return;
}

int
main (int argc, char *argv[])
{
    f (10, (long double)12.34, (long long int)13, 14);
    return 0;
}

Avviando il programma di esempio si deve visualizzare il messaggio seguente:

w = 10; x = 12.340000; y = 13; z = 14

596.3   Promozione

Va ricordato che gli argomenti delle chiamate alle funzioni vengono adattati in modo tale da facilitare l'uso della pila dei dati. Pertanto, i valori che prevedono una rappresentazione in memoria troppo piccola, subiscono quella che è nota come «promozione».

La funzione che utilizza una quantità di argomenti variabili, dovrebbe gestire solo valori che non possono subire una trasformazione di questo tipo, altrimenti, quando utilizza la macro-istruzione va_arg deve indicare un tipo adeguato alla promozione che si prevede sia applicata ai valori degli argomenti.

A questo proposito si può notare che nell'esempio di utilizzo apparso nel capitolo, non si fa mai uso di tipi di dati di rango inferiore a int.

596.4   Riferimenti


Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome c_171_stdarg_h_187.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory