La memoria è organizzata in celle di dimensione fissa (tipicamente 8 bit, cioè 1 byte). Ogni cella ha un indirizzo unico.
Dimensione Variabili
Ogni variabile occupa un certo numero di celle consecutive:
Un char occupa 1 cella.
Un int tipicamente occupa 4 celle (4 byte).
Pesi dei datatypes
Type
Size (bytes)
int
at least 2, usually 4
char
1
float
4
double
8
short int
2 usually
unsigned int
at least 2, usually 4
long int
at least 4, usually 8
long long int
at least 8
unsigned long int
at least 4
unsigned long long int
at least 8
signed char
1
unsigned char
1
long double
at least 10, usually 12 or 16
Dimensione Puntatori
La dimensione di un puntatore dipende dall’architettura del sistema:
Su sistemi a 32 bit: 4 celle (4 byte).
Su sistemi a 64 bit: 8 celle (8 byte).
Lo spazio occupato da un puntatore non dipende dal tipo che punta, infatti un puntatore rappresenta un indirizzo di memoria in cui è presente l’elemento che stiamo puntando, quindi:
La sintassi dei puntatori è composta da due simboli speciali * e &, dove in particolare * in base al contesto assume significati diversi.
Dichiarazione
Possiamo utilizzare la sintassi datatype *var_name per dichiarare un puntatore.
char *pc;
In questo caso stiamo dicendo che pc è un puntatore ad un area di memoria di 1 byte (grandezza di un char).
Più a basso livello la variabile p contiene l’indirizzo della cella di memoria che sta puntando.
Dereferenziazione (modifica/lettura)
Possiamo utilizzare l’operatore di dereferenziazione * per accedere all’indirizzo di memoria puntato dal puntatore e leggere/modificare il valore contenuto.
In C è possibile accedere all’indirizzo di una variabile attraverso l’operatore &, possiamo utilizzare questo operatore per puntare variabili già esistente.
char c = 'x'pc = &c
Scriviamo pc = &c e non pc* = &c perché:
Sintassi
Significato
Corretto?
pc = &c;
Assegna a pc l’indirizzo di c
✔️
*pc = c;
Assegna al valore puntato da pc il valore di c
✔️
*pc = &c;
Assegna al valore puntato da pc l’ indirizzo di c
❌
pc = c;
Assegna a pc (che dovrebbe contenere un indirizzo) il valore di c (ovvero 'x')
❌
Tip
int *px = &x;int y = *px
Possiamo leggere:
int *px = &x⇒ il puntatore ad intero px contiene l’indirizzo della variabile x.
int y = *px⇒ la variabile intera y contiene il valore contenuto dalla indirizzo di memoria puntato da px.
Relazione tra Array e Puntatori
Prima di tutto dobbiamo ricordare cos’è un array:
Array
Un array è un blocco consecutivo di celle in memoria.
La dichiarazione di un array di interi, ad esempio int arr[2];, riserva 8 celle consecutive (4 per ogni intero).
In C una “variabile array” come int arr[4] può essere visto come un puntatore infatti arr rappresenta l’indirizzo della prima cella (elemento di indice 0).
Stampando l’indirizzo di arr e quello del primo elemento ar[0], si ottiene lo stesso valore:
printf("%p", arr); // Indirizzo dell'array printf("%p", &arr[0]); // Indirizzo del primo elemento
Per questo motivo, un array può essere trattato come un puntatore al suo primo elemento.
TEST: (da provare)
x = 4 // indirizzo 1000int *px = &x; // indirzzo di px è 3000 e contiene 1000 (indirizzo di x)print(&px); //out: 3000print(px); //out: 1000print(*px); // out: 4*px = 5print(x) // out: 5
int *arr = {1,2} // 1 in indizizzo 1000, 2 indirizzo 1004 // arr è salvato nel indirizzo 600print(arr) // out: 1000print(*arr) // out: 1print(arr[0]) // out: 1print(arr[1]) // out: 2print(*(arr+4)) //out: 2int **pa = &arr; // puntatore all'indirizzo di memoria del arrprint(pa); // 600print(*pa); // 1000print(**pa); // 1