prof. Nunzio Brugaletta | Programmazione e linguaggio C |
Si è già fatto notare che, nel linguaggio C, il nome di un vettore è praticamente il puntatore al primo elemento della struttura ossia, per quanto detto precedentemente, l’indirizzo base. Ciò porta alla considerazione che l’elemento generico del vettore è accessibile oltre che, come già osservato, cioè come l’elemento di posizione i della struttura, anche come l’elemento il cui indirizzo può essere calcolato a partire dall’indirizzo base, dalla lunghezza dell’elemento e dalla posizione relativa sebbene, per motivi legati alla comprensibilità delle istruzioni, è più opportuno accedere agli elementi di un vettore utilizzando l’indice.
Programma A |
Programma B |
---|---|
#define QEL 5
...
void carica(int *v1){
int i;
for(i=0;i<QEL;i++){
printf("\nElemento n°%d ",i+1);
scanf("%d",(v1+i));
}
}
...
void comunica(const int *v1){
int i;
for(i=0;i<QEL;i++)
printf("%d ",*(v1+i));}
|
#define QEL 5 ... void carica(int *v1){ int i; for(i=0;i<QEL;i++){ printf("\nElemento n°%d ",i+1); scanf("%d",&v1[i]); } } ... void comunica(const int *v1){ int i; for(i=0;i<QEL;i++) printf("%d ",v1[i]);} |
L’input e l’output, dell’elemento generico di un vettore di elementi di tipo int, nel Programma B viene effettuato al solito modo. Nel Programma A l’input viene effettuato specificando l’indirizzo dove deve essere conservato il dato. Il nome v1 è un puntatore ed è bene chiarire che sommare il valore di i a tale puntatore significa, come fatto rilevare quando si è trattata la struttura sequenziale, spostarsi all’i-esimo elemento. In altri termini, per esempio: a+1 se a è una variabile di tipo int vuol dire sommare il valore 1 al valore esistente, se invece a è un puntatore a int significa incrementare l’indirizzo contenuto in a di tante posizioni quante ne sono previste dal tipo int. Nel caso dell’istruzione di input l’istruzione v1+i equivale a INDb+(i-1)l infatti v1 rappresenta l’indirizzo base, i-1 nel nostro caso si traduce in i poiché si parte dal valore 0, in quanto a l questo è contenuto implicitamente nella dichiarazione del puntatore (è dichiarato come puntatore ad int, quindi il compilatore conosce la lunghezza degli elementi della struttura). In questo modo l’array viene gestito nella sua rappresentazione come struttura interna.
Nell’input non è utilizzato l’operatore & poiché in ciò che è scritto è già espresso un indirizzo. Un discorso simile occorre farlo per l’output: v1+i è un puntatore e quindi al programma interessa il valore contenuto nella memoria puntata.
Sui puntatori possono essere quindi effettuate operazioni aritmetiche, è questo infatti quello a cui si fa riferimento quando si parla di aritmetica dei puntatori, solo che bisogna tenere presente il senso che assumono tali operazioni: aggiungere il valore 1 a un puntatore vuol dire spostarsi di tante locazioni di memoria quante ne bastano per trovare il prossimo elemento dello stesso tipo. Da questo punto di vista dovrebbe risultare chiara, per esempio, la convenzione utilizzata nel passaggio di un array a più dimensioni ad una funzione: vengono infatti specificate tutte le dimensioni tranne la prima. Tutto ciò è comprensibile se si tiene presente che un array, per esempio a due dimensioni, è conservato in memoria per righe successive (la prima riga, poi la seconda ecc..); in questo caso la conoscenza della quantità di colonne serve per acquisire conoscenza sulle dimensioni del singolo elemento (in questo caso un elemento è composto da una intera riga dell’array).
http://ennebi.solira.org | ennebi@solira.org |