Array statici

  1. gli array sono insiemi di variabili
  2. si chiamano statici perchè hanno dimensione fissa
  3. come si dichiarano
  4. zone di memoria occupate dagli elementi di un array
  5. indirizzo e sizeof di un intero vettore
  6. dimensione=numero elementi/sizeof=numero byte occupati

Gli array sono insiemi di variabili dello stesso tipo. Le singole variabili di un array sono dette elementi. Ogni elemento è identificato da un intero, detto indice. Gli array la cui dimensione viene specificata all'interno del codice si chiamano array statici, dato che la loro dimensione non cambia durante l'esecuzione del programma. I due modi per dichiarare un array statico sono:

  1. specificando la dimensione
  2. dando gli elementi iniziali

Il seguente programma statici.c crea due vettori a e b, il primo di interi e il secondo di numeri reali. Si usando i due meccanismi di dichiarazione: il primo vettore viene dichiarato dando la sua dimensione, per il secondo diamo gli elementi che deve inizialmente contenere.

/*
  I due modi di dichiarare un array statico.
*/

int main() {
  int a[10];
  float b[]={0.12, 3.23, 1.23, 1e2, -12.43};

  return 0;
}

In tutti e due i metodi di dichiarazione, il numero di elementi del vettore è specificato nel codice del programma. Nel primo caso, il numero fra parentesi quadre è 10, quindi il vettore contiene dieci elementi. Nel secondo caso, non ci sono numeri fra parentesi, ma la lista dei valori iniziali contiene 5 elementi, quindi il vettore contiene cinque elementi. Il numero di elementi di questi due vettori rimane sempre lo stesso durante tutta l'esecuzione del programma. Questo è il motivo per cui questi array vengono detti statici.

Un vettore si può pensare come un insieme di variabili dello stesso tipo. Ogni variabile di un vettore viene identificata dal nome del vettore più un numero intero positivo. Nell'esempio di sopra, la dichiarazione dell'array int a[10]; crea un insieme di variabili a[0], a[1], ecc. fino ad a[9]. Ognuna di queste variabili è caratterizzata da un indirizzo, un numero di byte occupati e un tipo. Tutte le variabili di uno stesso vettore hanno lo stesso tipo, e quindi tutte occupano lo stesso spazio di memoria. I loro indirizzi sono invece differenti. Il programma indstatico.c, riportato qui sotto, stampa indirizzo e byte occupati da ognuna delle variabili che compongono il vettore a.

/*
  Indirizzi e byte occupati dagli elementi di un array statico.
*/

int main() {
  int a[10];
  float b[]={0.12, 3.23, 1.23, 1e2, -12.43};

  int i;

  for(i=0; i<=9; i++)
    printf("a[%d] ha indirizzo=%x ed occupa %d byte\n",
           i, &(a[i]), sizeof(a[i]) );

  return 0;
}

Se si prova a compilare ed eseguire questo programma, si ottiene una stampa di questo genere:

a[0] ha indirizzo=bffff3f4 ed occupa 4 byte
a[1] ha indirizzo=bffff3f8 ed occupa 4 byte
a[2] ha indirizzo=bffff3fc ed occupa 4 byte
a[3] ha indirizzo=bffff400 ed occupa 4 byte
a[4] ha indirizzo=bffff404 ed occupa 4 byte
a[5] ha indirizzo=bffff408 ed occupa 4 byte
a[6] ha indirizzo=bffff40c ed occupa 4 byte
a[7] ha indirizzo=bffff410 ed occupa 4 byte
a[8] ha indirizzo=bffff414 ed occupa 4 byte
a[9] ha indirizzo=bffff418 ed occupa 4 byte

Tutti gli elementi di uno stesso array hanno la stessa dimensione. Questo è assolutamente ragionevole, dato che sono tutte variabili dello stesso tipo (gli array sono per definizione composti da variabili di un tipo). Essendo inoltre variabili diverse, i loro indirizzi sono tutti diversi. Se al contrario due elementi fossero associati allo stesso indirizzo, modificare l'uno sarebbe equivalente a modificare l'altro, cosa che non ci si aspetta che avvenga. Per lo stesso motivo, è chiaro che le zone di memoria che corrispondono a due elementi diversi non devono sovrapporsi neanche parzialmente.

Un altro fatto che risulta evidente dalla stampa di sopra è che le aree di memoria delle variabili sono consecutive: prima ci sono i quattro byte di a[0], i successivi quattro sono quelli di a[1], ecc. Questo fatto vale per tutti gli array (anche quelli di char, quelli di float, ecc.)

La figura qui accanto dà una rappresentazione grafica della memoria occupata da questo vettore (rispetto alle figure precedenti, usiamo rettangoli più schiacciati per rappresentare i byte).

Quale zona di memoria occupa questo vettore? Il primo byte occupato dall'intero vettore è anche il primo occupato da a[0], quindi il primo byte occupato dall'intero vettore si può trovare come &(a[0]). Dal momento che ogni elemento occupa sizeof(int) byte, il numero totale di byte occupati è dato dal numero degli elementi del vettore moltiplicato per sizeof(int).

Questi due valori, indirizzo e numero di byte occupati da un vettore statico, si possono trovare anche usando & e sizeof sull'intero vettore. In particolare, applicando & sul vettore, si trova l'inizio della zona di memoria occupata dal vettore (che coincide con l'inizio della zona di memoria occupata dal suo primo elemento), mentre sizeof dice il numero di byte occupati dal vettore (che è uguale al numero di elementi del vettore moltiplicato per la dimensione di ognuno di essi). Il seguente programma indvett.c stampa indirizzo e numero di byte occupati da un vettore statico.

/*
  Indirizzo e numero di byte di un vettore statico.
*/

int main() {
  int a[10];
  float b[]={0.12, 3.23, 1.23, 1e2, -12.43};

  printf("a ha indirizzo=%x e occupa %d bytes\n", &a, sizeof(a));

  printf("indirizzo del primo elemento=%x\n", &(a[0]));
  printf("byte occupati da ogni elemento=%d\n", sizeof(a[1]));

  return 0;
}

L'esecuzione di questo programma genera un risultato di questo tipo (i valori numerici dell'indirizzo possono ovviamente cambiare):

a ha indirizzo=bffff428 e occupa 40 bytes
indirizzo del primo elemento=bffff428
byte occupati da ogni elemento=4

È chiaro che &a e &(a[0]) coincidono. Si vede anche chiaramente che il numero di byte occupati dal vettore è uguale al numero di byte occupati da ogni elemento moltiplicato per il numero di elementi.

Nota importante.

In questa e in alcune pagine successive, si parla di dimensione di un vettore, intendendo il numero di elementi che lo compongono. Per esempio, il vettore dichiarato con int a[10]; è composto da 10 elementi, quindi ha dimensione 10. Per indicare il risultato della sizeof, usiamo invece il termine ``numero di byte occupati''. Il alcuni testi si può trovare ``dimensione'' come sinonimo dello spazio occupato da una variabile. Il contesto permette di solito di capire di cosa si sta parlando.