Puntatori
in C e C++
La memoria
• La memoria del calcolatore è suddivisa in due parti:
o Stack (statica)
o Heap (dinamica)
• Nello Stack vengono immagazzinate tutte le
variabili
• Es int x;
o riserva sullo stack due byte per la variabile x
• L’allocazione sullo stack è statica (non è possibile
modificare il numero di byte assegnati a una
variabile)
Heap
• E’ una memoria dinamica
• Il programmatore può allocare e deallocare la
memoria a suo piacimento.
• La gestione diretta della memoria (allocazione e
deallocazione) è un'operazione molto delicata
che, se compiuta in modo errato, può portare ad
errori runtime spesso difficili da individuare.
• La gestione dell'Heap avviene tramite i puntatori.
Puntatore
•
•
•
•
•
•
Una variabile puntatore è una variabile che contiene l'indirizzo di memoria di un'altra
variabile.
Utilità dei puntatori:
o Nelle funzioni (passaggio per referenza, che permette la modifica degli argomenti in
input);
o Per l’allocazione dinamica della memoria (definizione di strutture dati di dimensione
variabile)
La dichiarazione di una variabile puntatore definisce il tipo della variabile puntata, la
specifica di puntatore (*) e il nome della variabile
Es: int *px;
o dichiara una variabile px che è un puntatore a un intero
In C++, per conoscere l'indirizzo di una variabile, è sufficiente far precedere al nome
della variabile l'operatore &.
Esempio:
int *px;
// px è un puntatore a un int
int x;
// x è una variabile int
px = & x;
// px punta alla zona di memoria di x
Operare con i puntatori
• Dichiarazione e definizione di un puntatore che punta a una
locazione di memoria contenenti un certo tipo di dato:
• tipo *nome_variabile
• es. int *x; char *y;
• & (operatore unario che restituisce l’indirizzo di memoria
dell’operando)
• Es. se la variabile n è allocata all’indirizzo 1200.
• Dopo l’esecuzione dell’istruzione:
• x=&n
• il valore di x è 1200.
Operazioni con i
puntatori
• Dopo l’istruzione px=&x si crea un’associazione fra
le due variabili
• x=5 e *px=5 risultano equivalenti: inseriscono il
valore 5 nella zona di memoria riservata a x
int a = 5;
int b = 8;
int* pa = &a;
int* pb = &b;
a
5
pa
b
8
pb
Esempio
#include <iostream>
using namespace std;
int main()
{
int a;
// a è un intero
int *aPtr;
// aPtr è un puntatore a un intero
a = 7;
aPtr = &a;
// aPtr punta allo stesso indirizzo di a
cout << "Indirizzo di a: " << &a << " Valore di aPtr " << aPtr << endl;
cout << "Valore di a: " << a << " Valore di *aPtr: " << *aPtr << endl;
cout << "Notare che * e & sono uno l'inverso dell'altro" << endl;
cout << "&*aPtr = " << &*aPtr << " *&aPtr = " << *&aPtr << endl;
}
Operatori
• * (operatore unario che restituisce il valore della locazione di
memoria puntata dall’operando).
• Es. se la variabile x ha come valore 1200, e la locazione 1200
contiene il valore 555.
• Dopo l’esecuzione dell’istruzione: y=*x;
• Il valore di y è 555.
• I puntatori possono essere confrontati tra di loro
• * è il complemento di &.
int x,y;
int x,y;
int *p;
è equivalente a
y=x;
p=&x;
y=*p;
Allocazione dinamica
della memoria in C
• malloc() alloca porzioni contigue di memoria e
restituisce l’indirizzo della locazione iniziale
• void *malloc(numero di byte)
• free() libera porzioni di memoria
• void free(void *p)
Es.
char *p;
p=malloc(1000);
alloca 1000 byte in sequenza e p punta alla locazione iniziale.
• La zona di memoria allocata attraverso malloc si trova in
un'area di memoria speciale, detta heap (memoria
dinamica).
Allocazione dinamica
della memoria in C++
• new <tipo>
• alloca nella memoria heap un certo numero di byte
sufficienti a contenere un dato di tipo <tipo> e restituisce
l’indirizzo del primo byte
• Es: int *px; px=new int; //alloca due byte
• new <tipo>[<dimensione>]
• alloca un array
• Es: int *pv; pv=new int[20]; // alloca 20 interi (40 byte)
• delete <variabile puntatore>
• dealloca la memoria puntata dalla <variabile
puntatore>
• Es: delete px;
NULL
• La costante NULL è di tipo void* (quindi compatibile
con tutti i tipi puntatore)
• indica un puntatore che non punta a nulla: non
può essere dereferenziato
Esempio – vettore
dinamico
int dimesione,i;
int *vet;
//sarà l’array dinamico
cout << "Dimensione dell’array da allocare: “;
cin >> dimensione);
vet = new int(dimensione);
// allocazione del vettore
// esempio di inserimento valori
for(i=0;i<dimensione;i++)
{
cout << "Inserisci elemento v[" << i << "] ";
cin >> vet[i];
}
Puntatori a strutture
• Esempio di struttura:
struct punto {
double x;
double y;
};
struct punto p1;
struct punto *pun;
pun=&p1;
• Notazione errata
*p1.x=5;
• Notazione corretta
(*p1).x=5;
• Notazione migliore
p1->x=5;
Aritmetica dei puntatori
• L’aritmetica dei puntatori si riferisce a un insieme di
operazioni aritmetiche applicabili sui valori di tipo
puntatore.
• Le operazioni hanno lo scopo di consentire
l'accesso a collezioni di dati omogenei conservati in
posizioni contigue di memoria (esempio array).
• L'aritmetica dei puntatori è tipica del linguaggio C
ed è stata mantenuta in alcuni linguaggi derivati (è
presente per esempio in C++ ma non in Java).
Aritmetica dei puntatori
in C
• L'aritmetica dei puntatori del C è basata su tre
operatori fondamentali, accompagnati da un
certo numero di altri operatori la cui semantica è
derivata da quella degli operatori principali:
• + operatore binario di somma di un puntatore e un
intero
o derivato: ++ operatore unario di autoincremento di un puntatore
o derivato: += operatore di assegnamento con somma
• - operatore binario di differenza fra due puntatori
• - operatore binario di sottrazione di un intero da un
puntatore
o derivato: --operatore unario di autodecremento di un puntatore
o derivato: -= operatore di assegnamento con differenza
Scarica

ppt - Alberto Ferrari