Linguaggio C - Tipi di dato complessi

Tipi derivati (o strutturati) complessi

Con il linguaggio C e' possibile combinare fra loro i tipi derivati, quali strutture, puntatori, array ed union, creando cosi' delle dichiarazioni piuttosto complesse dei tipi.
Per la dichiarazione dei tipi complessi si fa ricorso alla stessa precedenza fra operatori cosi' come e' definita dalla sintassi delle espressioni.
Esempio:
  char *a[10];          /* array di 10 elementi di tipo puntatore a char
                           (ogni elemento e' un puntatore) */

  char (*b)[10]         /* puntatore ad un array di 10 elementi di tipo char.
                           *(b+1) punta al successivo array di 10 elementi */

  struct s1             /* dichiarazione della struttura s1 */
    {
    int campo1;
    int campo2;
    float campo3;
    };

  struct s1 *p;         /* p e' un puntatore alla struttura s1 */  

  struct s2             /* dichiarazione della struttura s2 */
    {
    int *campo1;
    int *campo2;
    float *campo3;
    }

  struct s2 c;         /* c e' una variabile di tipo struct s2 */  
    

Per l'accesso ai campi di una struttura puntata da un puntatore, sarebbe necessario utilizzare gli operatori * (dereferencing) e . (accesso ai campi).
Poiche' l'operatore . ha priorita' maggiore rispetto all'operatore *, si rende necessario l'uso di parentesi.
Esempio:

  (*p).campo1 = 10;     /* assegno il  valore 10 all'elemento campo1
                           della struttura puntata da p */

  *c.campo1 = 10;       /* assegno il  valore 10 all'area di memoria puntata
                           da campo1.
                           campo1 e' un puntatore facente parte della struttura
                           definita da c */
    
Visto l'uso piuttosto frequente dei puntatori a struttura (1° caso dell'esempio), la sintassi del C ha messo a disposizione l'operatore ->
Esempio:
  ...
  struct data                   /* dichiarazione della struttura data */
    {
    int y;              /* anno */
    int m;              /* mese */
    int d;              /* giorno */
    };

  typedef struct data  s_data;  /* per comodita' */

  s_data *pData;                /* puntatore a s_data */
    /* equivale a:
     * struct data *pData;
     */

  ...

  pData = (s_data *)malloc(sizeof(s_data));
  if (pData == NULL)
    {
    /* gestione errore indisponibilita' memoria */
    ...
    }

  (*pData).y = 2000;            /* inizializzazione anno */
  (*pData).m = 7;               /* inizializzazione mese */
  (*pData).d = 19;              /* inizializzazione giorno */
  
    /* oppure */

  pData->y = 2000;              /* inizializzazione anno */
  pData->m = 7;                 /* inizializzazione mese */
  pData->d = 19;                /* inizializzazione giorno */
    
Nell'esempio riportato, il secondo modo di inizializzare i campi della struttura e' da preferirsi al primo, in quanto risulta essere piu' leggibile, quindi meno ambiguo e piu' mantenibile del primo metodo.


Indice-C Indice linguaggio C
At Home Umberto Zappi Home Page