25
Laboratorio di Informatica – Antonio Monteleone 60 Operatore di indirizzo • L’ operatore unario di indirizzo & restituisce l’indirizzo della locazione di memoria dell’operando Il valore restituito non va usato come l- value (in quanto l’indirizzo di memoria di una variabile non può essere assegnato in un’istruzione, ma è predeterminato) &a; // ok &(a+1); // errore &a = b; // errore l’indirizzo di memoria di una variabile non può essere modificato in un’istruzione, ma solo usato come riferimento in quanto è predeterminato e non modificabile)

•L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

  • Upload
    doduong

  • View
    213

  • Download
    0

Embed Size (px)

Citation preview

Page 1: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 60

Operatore di indirizzo• L’ operatore unario di indirizzo &

restituisce l’indirizzo della locazione di memoria dell’operando

• Il valore restituito non va usato come l-value (in quanto l’indirizzo di memoria di una variabile non può essere assegnato in un’istruzione, ma è predeterminato)

&a; // ok&(a+1); // errore&a = b; // errore

l’indirizzo di memoria di una variabile non può essere modificato in un’istruzione, ma solo usato come riferimento in quanto è predeterminato e non modificabile)

Page 2: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 61

Puntatori• Una variabile di tipo puntatore contiene

l’indirizzo di memoria di un’altra variabile (detta variabile puntata) la quale contiene un valore specifico

j

12

ptr

int main()

{

int j = 12;

int *ptr = &j;

cout << *ptr << endl;

j = 24;

cout << *ptr << endl;

cout << ptr << endl;

return 0;

}

12

24

0x7b03a928

Page 3: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 62

Dichiarazione di puntatori• Nella dichiarazione si usa *

int *ptr; // ptr è un puntatore a variabile di tipo int• Un dato puntatore può puntare solo al tipo di variabili

specificato nella dichiarazionefloat a = 10; int b = 12;int *ptr1;ptr1 = &a; // errore sintatticoptr1 = &b; // Ok

• Si può anche dichiarare un puntatore a puntatoredouble **ptr_ptr;

• La dichiarazione di un puntatore comporta allocazione di memoria per la variabile puntatore, non per la variabile puntata

Page 4: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 63

Operazioni sui puntatori• Assegnazione di un valore int i = 10;int *p = &i;int *q = p;

• Uso del puntatore per riferirsi all’oggetto puntato*p = 3; // dereferenziazione

• Confronto tra puntatori (==, !=)if (p != q)*p = 3;

Page 5: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 64

Aritmetica dei puntatori• Il valore assunto da un puntatore è un numero intero che

rappresenta, in byte , un indirizzo di memoria• le operazioni di somma fra un puntatore e un valore intero

(con risultato puntatore), oppure di sottrazione fra due puntatori (con risultato intero) vengono eseguite tenendo conto del tipo della variabile puntata

• Es.: se si incrementa un puntatore a float di 3 unità, il suo valore viene incrementato di 12 byte.

• Se l’espressione p rappresenta l’indirizzo di un oggetto di tipo T, allora l’espressione p + 1 rappresenta l’indirizzo di un oggetto di tipo T allocato consecutivamente in memoria.

• Se i è un intero e p rappresenta l’indirizzo addr di T che occupa n locazioni di memoria, allora l’espressione p+i ha valore addr+n*i

Page 6: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 65

L’operatore di dereferenziazione• L’operatore unario di derefenziazione di un

puntatore restituisce il valore della variabile puntata dall’operando

1. Come r-value esegue un’operazione di estrazionea = *p;

// assegna ad a il valore della variabile puntata da p2. Come l-value, esegue un’operazione di

inserimento*p = a;

// assegna il valore di a alla variabile puntata da p

Page 7: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 66

L’operatore di dereferenziazione (2)• L’operazione di dereferenziazione è inversa a

quella di indirizzo: se assegniamo a un puntatore p l’indirizzo di una variabile a allora la derefenziazione *p di p coincide col valore della variabile a#include <cassert>int main()

{double a = 10;double *p = &a; // assert(*p == a);return 0;

}

Page 8: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 67

L’operatore di dereferenziazione (3)

• Puntatore nullo

#include <iostream>

int main(){int j = 12;int *ptr = 0;cout << *ptr << endl; // crash !

double * dPtr = 0;

if (j >0)

{

double a = 10;

dPtr = &a;

} // a va out of scope

cout << *dPtr << endl // crash !

return 0;}

Segmentation violation(core dumped)

j

12

ptr

• Dangling pointer

a

10

dPtr

Page 9: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 68

I puntatori e il qualificatore const

• Mediante la parola chiave const1. E’ possibile specificare che un dato puntatore

non deve essere usato per modificare l’oggetto puntatoint x = 10, y = 20;const int *ptr1 = &x;*ptr1 = 20; // errore di compilazione

2. E’ possibile specificare che un puntatore non deve essere modificatoint * const ptr2 = &x;ptr2 = &y; // errore di compilazione

Page 10: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 69

Puntatori e array

• In C++ gli array sono trattati come puntatori

int main(){float x[5];int j;for (j = 0; j < 5; j++)

x[j] = 0;

float *ptr = x;*ptr = 1.5; // x[0] = 1.5*(ptr+1) = 2.5; // x[1] = 2.5*(ptr+3) = 3.5; // x[3] = 3.5

}

X

X[0]1.5

X[1] X[2] X[3] X[4]2.5 0.0 3.5 0.0

X+1 X+3

Page 11: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 70

Aree di memoria• In C++ è possibile distinguere due aree distinte di

memoria: memoria stack e memoria heap

• E’ possibile allocare aree di memoria dinamicamente durante l’esecuzione del programma ed accedere ad esse mediante puntatori.

• Gli oggetti così ottenuti sono detti dinamici ed allocati nella memoria libera.

Page 12: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 71

Memoria stack• L’area di memoria stack é quella in cui viene

allocato un “pacchetto” di dati non appena l’esecuzione passa dal programma chiamante a una funzione .Questo “pacchetto” contiene:- l’indirizzo di rientro nel programma chiamante- la lista degli argomenti passati alla funzione

• Esso viene “impilato” sopra il pacchetto precedente (quello del progr. chiamante) e poi automaticamente rimosso dalla memoria appena l’esecuzione della funzione é terminata.

Page 13: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 72

Memoria stack (2)• Nella memoria stack vengono sistemati anche i dati relativi

a tutte le variabili automatiche (cioè locali e non statiche) create dalle funzioni.

• Il loro “ tempo di vita” é legato all’esecuzione della funzione proprio perché, quando la funzione termina, l’intera area stack allocata viene rimossa.int sum(int a[], int len) {int temp=0;for (int i=0; i<len; i++)temp += a[i];

return temp;}

int main() {int vect[4] = {1,2,3,4};int tot = sum(vect, 4);cout << “somma “ << tot << endl;return 0;

}

Page 14: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 73

Memoria heap• L’area heap non é allocata automaticamente, ma

solo su esplicita richiesta del programma ( allocazione dinamica della memoria)

• L’area allocata non é identificata da un nome, ma è accessibile solo tramite dereferenziazione di un puntatore

• Il tempo di vita coincide con l’intera durata del programma, a meno che non venga esplicitamente deallocata; se il puntatore va out of scope, l’area non è più accessibile, ma continua a occupare memoria inutilmente (memory leak).

Page 15: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 74

new e delete• Gli operatori new and delete vengono utilizzati per

allocazione/deallocazione di memoria dinamica– la memoria dinamica (heap), è un’area di memoria libera

provvista dal sistema per quegli oggetti la cui durata di vita è sotto il controllo del programmatore

• new riserva la quantità necessaria di memoria richiesta e ritorna l’indirizzo di quest’area

int *i=new int; //alloca un intero, ritorna il puntatorechar *c=new char[100]; //alloca un array di 100 caratteriint *i=new int(99); //alloca un intero e lo inizializza a 99char *c=new char(‘c’); //alloca un carattere inizializzato a cInt *j=new int[n][4]; //alloca un array di puntatori ad intero

Page 16: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 75

new e delete (2)• L’operatore delete è usato per restituire una certa

area di memoria (allocata con new) allo heap• Ogni oggetto allocato con new deve essere distrutto con delete se non viene piu` utilizzato, altrimenti l’areadi memoria che esso occupata non potra` piu` essere ri-allocata (memory leak)

• L’argomento di delete è tipicamente un puntatoreinizializzato preventivamente con new

delete ptr; // distrugge un puntatore ad un oggettodelete p[i]; // distrugge l’oggetto p[i]delete [] p; // distrugge ogni oggetto di tipo p

Page 17: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 76

new e delete (3)

• Attenzione– la dimensione dello heap non e` infinita– l’allocazione con new può fallire, nel qual caso new

restituisce un puntatore nullo o suscita un’eccezione. Nel caso di allocazione di memoria importantebisogna verificare che l’operazione abbia avutosuccesso prima di usare il puntatore

– ogni oggetto creato con new deve essere distruttocon delete, ogni oggetto creato con new[] deveessere distrutto con delete[] , queste forme NONsono intercambiabili

Page 18: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 77

Puntatori: allocazione dinamica• Riferimento ad una locazione di memoria

#include <iostream>

int main(){int *ptr = new int;

*ptr = 12;cout << *ptr << endl;

delete ptr;return 0;

}

12

ptr

• Attenzione:– Non usare delete fa accumulare locazioni di

memoria inutilizzate (memory leak)– Utilizzare puntatori prima del new o dopo il delete causa il crash del programma

Page 19: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 78

Puntatori: allocazione dinamica

• Riferimento a più locazioni di memoria#include <iostream>

int main(){int *ptr = new int[3];

ptr[0] = 10;ptr[1] = 11;ptr[2] = 12

delete [] ptr;return 0;

}

10

ptr

11 12

Page 20: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 79

Regole di conversione e cast• In C++ esistono conversioni esplicite ed implicite.

Le conversioni implicite (e.g. int →float) nelleespressioni aritmetiche, nel passare i parametri ad unafunzione o nel ritornare un valore da una funzionerendono il meccanismo di conversione molto conveniente ma anche potenzialmente pericoloso(errori a run time)

•char, short e bool vengono promossi ad int•Tipi interi che non possono essere rappresentati con un int

vengono promossi a unsigned•In una espressione di tipo misto, gli operandi di ordine

inferiore vengono promossi all’ordine superiore secondola gerarchia:

int<unsigned<long<unsigned long<float<double<long double•bool e` un tipo intero, con true che viene promosso a 1 e false

a 0

Page 21: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 80

Regole di conversione e cast (2)• Ogni genere di puntatore può essere convertito in

un puntatore generico a void• Al contrario di quanto avviene in C, un puntatore

generico non è compatibile con un puntatore ditipo arbitrario ma richiede un cast esplicito

• Ogni puntatore puo` essere inizializzato a 0 senzabisogno di un cast esplicito.

• In C++ usare 0 e non NULL per i puntatori!

char *ch;void *generic_p;. . .generic_p=ch; // OK, char* va in void*ch=generic_p; // OK in C, illegale in C++ch=(char *)generic_p; // OK, C e C++ arcaico

Page 22: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 81

Casting in ANSI C++• Data la complessità delle operazioni di casting in C++ nuovi

operatori di casting sono stati aggiunti a quelli già esistentiin C

• Esiste anche un dynamic_cast, utilizzato per riconoscere il tipo di un oggetto a run-time (RTTI)

x=(float) i; // cast in C++ - notazione Cx=float(i); // cast in C++, notazione funzionale

x=static_cast<float>(i); // ANSI C++ - raccomandatoi=reinterpret_cast<int>(&x) // ANSI C++, non portabile e

// system dependent

func(const_cast<int>(c_var)) // dove C_var e` una// variabile dichiarata// const. Usato per // eliminare la “const-ness” // per chiamare func

Page 23: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 82

L’operatore static_cast• L’operatore static_cast<tipo>(espressione)

è usato per convertire un tipo in un altro, compatibile con il primo. int a = static_cast<int>(12.45); // da double a int

• L’espressione a += b; // a di tipo int, b di tipo double

è valutata dal compilatore come se fossea=static_cast<int>(static_cast<double>(a)+b);

Si ha lo stesso risultato esplicitando il casta += static_cast<int>(b);

Page 24: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 83

L’operatore const_cast• L’operatoreconst_cast<tipo>(espressione)

è usato per eludere l’attributo const del suo operando

void fun(char *s); // non altera la stringa

int main() {char const hello[] = “ciao“;

fun(hello) // errore// cannot convert parameter 1 from 'const char [5]' to 'char *‘

fun(const_cast<char *>(hello)); // OK

return 0;}

Elimina la const-ness

Page 25: •L’ operatore unario di indirizzo & - Università degli Studi di Roma … · • In C++ è possibile distinguere due aree distinte di memoria: memoria stack e memoria heap •

Laboratorio di Informatica – Antonio Monteleone 84

L’operatore reinterpret_cast• L’operatorereinterpret_cast<tipo>(espressione)è usato per reinterpretare i bit che compongono il suo argomento

void swap(char *c1, char *c2); // scambia i due argomentivoid swap(char &c1, char &c2); // parametri per riferimento

void swapLong(long *a) // scambia i byte dell’argomento{char *c = reinterpret_cast<char*> (a);swap(c, c+3); // swap(c[0], c[3]); swap(c+1, c+2); // swap(c[1], c[2]);

}