Puntatori






Aree di memoria sono gestibili mediante puntatori La posizione di una variabile, all'interno della memoria, è individuata dall'indirizzo della variabile medesima; noto l'indirizzo è possibile leggere/modificare il valore di tale variabile. Nel caso di un array, individuare la posizione di un elemento ci permettere di accedere all'elemento medesimo ed anche a tutti gli altri.





 
Equivalenza tra notazione con [] ed aritmetica dei puntatori Dopo aver allocato un'area di memoria, per accedere a ciascun elemento dell'area stessa si possono utilizzare due diversi metodi: l'aritmetica dei puntatori e gli indici.
I due sono perfettamente equivalenti ovvero, una volta specificato quale sia l'elemento che prendiamo come origine, entrambe le notazioni indicano di quante posizioni è necessario muoversi per individuare l'elemento che ci interessa raggiungere.










Approfondiamo un po' la parte evidenziata in blu ...



Esercizio:

1) Dichiarare ed implementare una funzione che alloca memoria sufficiente a contenere un array di variabili di tipo int; la dimensione dell'array sia posta pari a lungh. La funzione deve inizializzare ciascun elemento dell'array con un valore pari a quell dell'indice corrispondente all'elemento stesso e restituire il puntatore all'area di memoria allocata.

2) visualizzare gli elementi dell'array che vanno dal sesto al decimo



Nota: la funzione deve restituire il puntatore ad un'area di memoria ; per poter ottenere un'area di memoria tale da non essere soggetta ai vincoli di durata cui sottostanno le variabili è necessario usare la funzione malloc(). Visto che malloc() restituisce un puntatore, il puntatore al primo elemento dell'area di memoria, gestisco tutti gli elementi facenti parte della memoria allocata da malloc() SOLO mediante tale puntatore (infatti, grazie all'aritmetica dei puntatori, noto il puntatore al primo elemento tutti gli altri sono univocamente individuati).






















// inizio esercizio

#include <stdio.h>

int* init_int(int);

int* init_int(int lungh)
{int *puntatore,i;
 puntatore = (int *) malloc(sizeof(int)*lungh);

 for(i = 0 ; i < lungh ; i++)
   {
    *(puntatore + i) = i ;
   }

/* la scrittura equivalente, usando la notazione degli array, è */

 for(i = 0 ; i < lungh ; i++)
   {
    puntatore[i] = i ;
   }

 return puntatore;
 }


/*


















Quindi, usare l'operatore di dereferimento risulta essere equivalente all'uso delle []. La cosa risulta palese in questo caso:

int *p_double;

p_double = (double *) malloc(sizeof(double));

Le due istruzioni che seguono sono equivalenti (una variabile è un array di un elemento !)

*p_double = 3.4 ;

p_double[0] = 3.4 ;

*/






























int main()
{int *vector;
 int * origine;
 int i = 0;
 vector = init_int(50);

/* ora l'array di interi è stato allocato ed è gestibile mediante il valore della variabile vector, ovvero il puntatore al primo elemento dell'array */

// visualizziamo gli elementi dell'array

 for(i = 5 ; i < 10 ; i++)
   printf("\n %d ", * (vector + i) );

 for(i = 5 ; i < 10 ; i++)
   printf("\n %d ", vector [ i ] );


// inizializziamo il secondo puntatore ad intero

 origine = vector + 5;


/*

vector         origine            
0
1
2
3
4
5
6
7
8
9
10
11


*/


 for(i = 0 ; i < 5 ; i++)
   printf("\n %d ", * (origine + i) );

 for(i = 0 ; i < 5 ; i++)
   printf("\n %d ", origine [ i ] );




























/*

vector                 origine    
0
1
2
3
4
5
6
7
8
9
10
11


*/

 origine = vector + 9;

 for(i = 4 ; i >=0 ; i--)
   printf("\n %d ", * (origine - i) );

 for(i = 4 ; i >=0 ; i--)
   printf("\n %d ", origine [ -i ] );


 free(vector);
 return 0;}


// fine esercizio




In conclusione: tutto ciò che viene gestito mediante array (ovvero usando le []) può essere gestito grazie ad un puntatore. Se l'array è composto da elementi di tipo TIPO (ove TIPO, per ora, è pari a int, char, float o double) il puntatore dovrà far essere dichiarato come TIPO * .
































Torniamo un istante agli array:

(1) fino a questo momento abbiamo costruito array di char, int, float e double

(2) l'array veniva costruito anteponendo al nome dell'array il tipo degli elementi dell'array stesso ed inserendo la dimensione dell'array tra parentesi []



Possiamo usare questa ricetta per creare un array di parole, ovvero un array di stringhe ?

Le stringhe si gestiscono mediante puntatori a char, sarà quindi necessario dichiarare un array di puntatori a char.



char * vettore[30] ;

/* dichiaro un array di nome vettore composto da 30 elementi di tipo char *. */

Ora, dopo aver dichiarato l'array, è necessario inizializzare i suoi elementi; essendo composto da puntatori, per inizializzare gli elementi dell'array in modo corretto è necessario allocare delle aree di memoria e assegnare gli indirizzi di tali aree agli elementi dell'array.




























for ( i = 0 ; i < 30 ; i ++ )
    vettore[i] = (char *) malloc (50 * sizeof(char));









Ora che la memoria è stata allocata possiamo trattare gli elementi del vettore come delle stringhe a tutti gli effetti.


















// inizio esempio

#include <stdio.h>
#include <string.h>


int main()
{char *stringhe[20];
 int i = 0;

// alloco memoria per le stringhe
  for( i = 0 ; i < 20 ; i ++ )
    stringhe[i] = (char *) malloc (30 * sizeof (char) );


// inserisco dei caratteri in una stringa

 strcpy( stringhe[0] , "prova di scrittura" ) ;


// chiedo all'utente di inserire caratteri in una stringa

  printf("inserisci una stringa avente al massimo 19 caratteri");
  scanf("%s", stringhe[1] ) ;


























/* inserisco un carattere all'interno di una stringa:
(a)
stringhe[2] è un puntatore a char, ovvero punta al primo elemento della stringa
(b) con l'aritmetica dei puntatori avanzo di 3 posizioni e ottengo il puntatore al quarto elemento
(c) applico l'operatore di dereferimento ed inserisco il valore */

 * (stringhe[2] + 3) = 'g' ;

/*
(d) visto che l'aritmetica dei puntatori è equivalente alla notazione con le []
*/

 stringhe[2][3] = 'g' ; // sembra tanto una tabella ...



 return 0; }

// fine esempio