Puntatori. Unità 6. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Documenti analoghi
Puntatori. Unità 6. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Introduzione al C. Unità 6 Puntatori. S. Salza, C. Ciccotelli, D. Bloisi, S. Peluso, A. Pennisi

Introduzione al C. Unità Gestione Dinamica della Memoria

Unità 11 Allocazione dinamica

Array. Parte 7. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Esercizi Array Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Esercizi Array. Parte 7. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Matrici. Parte 7. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Parte II ing. Domenico Daniele Bloisi, PhD

Passaggio parametri puntatore Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Char. Parte 2. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Funzioni. Unità 1. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Array. Unità 7. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Allocazione dinamica della memoria

Passaggio parametri puntatore

Puntatori in C. Puntatori. Variabili tradizionali Esempio: int a = 5; Proprietà della variabile a: nome: a

Istruzioni Condizionali

Esercitazione 6. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR. Domenico Daniele Bloisi

Ogni variabile in C è una astrazione di una cella di memoria a cui corrisponde un nome, un contenuto e un indirizzo.

Laboratorio di Informatica Ingegneria Clinica Lezione 14-16/11/2011

Verso i puntatori: Cosa è una variabile?

Stringhe Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Istruzioni Condizionali

Esercizi con Array. Unità 7. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Char. Unità 2. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Il linguaggio C. Puntatori e dintorni

Variabili dinamiche. Obiettivi: Presentare le variabili dinamiche, allocate e deallocate nell area HEAP, e le funzioni malloc e free

Strutture Dati Dinamiche

! Per quanto sappiamo finora, in C le variabili sono sempre definite staticamente

Per quanto sappiamo finora, in C le variabili sono sempre definite staticamente. per variabili di tipo array, in cui dover

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Matrici. Unità 7. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

La gestione della memoria dinamica Heap

Passaggio parametri puntatore

Unità Didattica 4 Linguaggio C. Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo.

Allocazione dinamica della memoria

Cosa è una variabile?

Operazioni sulle stringhe Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

VARIABILI AUTOMATICHE E DINAMICHE. Manuale linguaggio C

puntatori Lab. Calc. AA 2006/07 1

Variabili. Unità 2. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Linguaggio C: Puntatori Valeria Cardellini

Esercitazione 5. Unità Domenico Daniele Bloisi

For e do. Parte 4. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Char e bool. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Matrici. Unità 7. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Variabili. Unità 2. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

Allocazione Dinamica. Allocazione Statica. malloc() La funzione malloc()

Gestione dinamica della memoria

Gestione della memoria

I puntatori. DD Cap.7 pp KP Cap.6 pp

Esercitazione 6. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

&v restituisce l indirizzo della zona di memoria allocata per v.

Definizione di classi

Introduzione al C. Lezione 4 Allocazione dinamica della memoria. Rossano Venturini. Pagina web del corso

Gestione della memoria

Controllo del flusso

Istruzioni Condizionali

Puntatori. Fondamenti di Programmazione

Liste concatenate e allocazione dinamica

Corso di Informatica A.A

Istruzioni di Ciclo. Unità 4. Domenico Daniele Bloisi

Laboratorio di Informatica

Il puntatore. Il puntatore

Tipi di dato. Unità 2. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Corso di Informatica A.A

Fondamenti di Informatica T. Linguaggio C: i puntatori

L'Allocazione Dinamica della Memoria nel linguaggio C

Istruzioni Condizionali

Introduzione al C. Unità 7 Array. S. Salza, C. Ciccotelli, D. Bloisi, S. Peluso, A. Pennisi

Uso avanzato dei puntatori Allocazione dinamica della memoria

Funzioni. Unità 1. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Introduzione al C Lez. 4

Allocazione dinamica della memoria: calloc() Se T è il nomed di un tipo, la chiamata calloc(n, sizeof(t)) è equivalente a malloc(n * sizeof(t))

Introduzione al C Lez. 4. Allocazione Dinamica della memoria

Lezione 12: Allocazione Dinamica della Memoria

Puntatori. Un puntatore contiene un numero che indica la locazione di memoria dove è presente la variabile puntata

Allocazione dinamica della memoria

Corso di Fondamenti di Informatica. Puntatori e Allocazione Dinamica

Allocazione statica della memoria

FIL I Puntatori. Michele Nappi biplab.unisa.it. 15/12/2014 M. Nappi/FIL 1

Definizione Allocazione e deallocazione di variabili Allocazione e deallocazione di vettori

POINTERS. Una variabile pointer è una variabile che ha come valore un indirizzo di memoria.

Corso di Informatica A.A

Strutture. Array dei nomi degli esami (MAX ESAMI è il massimo numero degli esami). Array con i crediti degli esami.

Liste concatenate e allocazione dinamica

Corso di Programmazione I

I PUNTATORI PARTE I. Manuale linguaggio C

Prof. G. Ascia. I puntatori. Fondamenti di Informatica

Transcript:

Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR Domenico Daniele Bloisi

Docenti Parte I prof. Silvio Salza salza@dis.uniroma1.it http://www.dis.uniroma1.it/~salza/fondamenti.htm Parte II ing. Domenico Daniele Bloisi, PhD bloisi@dis.uniroma1.it http://www.dis.uniroma1.it/~bloisi/didattica/fondinf1112.html Nota: %7E corrisponde alla tilde ~ Ricorsione Pagina 2

Informazioni Generali ing. Domenico Daniele Bloisi, PhD Dipartimento di Informatica e Sistemistica Via Ariosto 25 (adiacente Piazza Dante, A fermate Manzoni, Vittorio Emanuele, Tram 3 fermata via Labicana) mailto:bloisi@dis.uniroma1.it http://www.dis.uniroma1.it/~bloisi Pagina 3

Ricevimento Su appuntamento. Inviare una email per conferma. DIS, via Ariosto 25 II piano, stanza B211 Si consiglia di controllare la bacheca degli avvisi http://www.dis.uniroma1.it/~bloisi/didattica/fondinf1112.html#avvisi Pagina 4

Sommario Memoria, indirizzamento e puntatori Tipo void * e conversioni sui puntatori Gestione dinamica della memoria Tempo di vita delle variabili allocate dinamicamente Problemi di deallocazione della memoria Passaggio dei parametri tramite puntatori Pagina 5

Memoria, indirizzamento e puntatori L accesso memoria di un calcolatore avviene attraverso un meccanismo di indirizzamento. In C il programmatore ha la possibilità di gestire gli indirizzi attraverso delle variabili che vengono definite di tipo puntatore. I valori delle variabili di tipo puntatore sono indirizzi di memoria, ossia dei valori numerici che fanno riferimento a specifiche locazioni di memoria. Pagina 6

Notazione grafica L indirizzamento si rappresenta graficamente tramite una freccia. Spesso non occorre conoscere lo specifico valore di una variabile di tipo puntatore (es. 00100). Pagina 7

Operatore indirizzo-di Per ottenere dei valori di tipo puntatore, cioè degli indirizzi, si utilizza l operatore & int i = 1; printf("l\' indirizzo di i e\' " "%p\n", &i); printf("mentre il valore di i e\' " "%d\n", i); stampa L' indirizzo di i e' 0028FF1C mentre il valore di i e' 1 Pagina 8

Operatore indirizzo-di L operatore & si chiama operatore indirizzo-di e restituisce l indirizzo della variabile a cui viene applicato. Nota: i = &10; non è ammesso dato che 10 è una costante int. Analogamente non si può accedere all indirizzo di una espressione. Nota: l indicatore di conversione per un indirizzo è %p (il formato è definito dall implementazione) Pagina 9

Operatore di dereferenziamento (indirizzamento indiretto) Quando si considera una variabile di tipo puntatore, l operatore * permette di recuperare il valore della locazione di memoria puntata. int i, j = 1; i = *&j; L istruzione i = *&j; assegna (con una notazione un po complicata) il valore della variabile j alla variabile i. Equivale, in pratica, all istruzione i = j; L operatore (unario) di indirizzamento indiretto * non deve essere confuso con l operatore di moltiplicazione (binario). Pagina 10

Operatore di dereferenziamento (indirizzamento indiretto) int i, j = 1; 00100 00200 i? j 1 i = *&j; &j 00200 *(&j) Valore contenuto in 00200 1 00100 00200 i 1 j 1 Pagina 11

Operatore & VS operatore * Se x è una variabile, &x denota l indirizzo in memoria di tale variabile. nome x &x α α indirizzo Se α è l indirizzo in memoria di una variabile, *α denota tale variabile: *α x Pagina 12

Variabili di tipo puntatore Per la gestione degli indirizzi occorre dichiarare delle variabili di tipo puntatore, specificando il tipo della locazione di memoria puntata. int *p1;... // allocazione di memoria (vedi dopo) *p1 = 10; dichiara una variabile di tipo puntatore ad intero ed assegna alla variabile puntata il valore 10. Pagina 13

Attenzione 1. La dichiarazione di una variabile puntatore non alloca memoria per la variabile puntata; prima di accedere alla variabile puntata bisogna allocare esplicitamente memoria (vedremo dopo come ) 2. Nelle dichiarazioni multiple tipo: int *p1, p2; p2 non è un puntatore! Pagina 14

Esempio: uso di variabili puntatore int i, j, k; int *pt_i, *pt_j; pt_i = &i; pt_j = &j; i = 1; j = 2; k = *pt_i + *pt_j; *pt_i = 10; printf("i = %d\n", i); printf("k = %d\n", k); Pagina 15

Diagramma della memoria Le variabili di tipo int i, j, k, vengono manipolate attraverso i puntatori alle locazioni di memoria ad esse associate al momento della dichiarazione. Pagina 16

Esecuzione Il programma stampa a video: i = 10 k = 3 Pagina 17

Assegnazione di un valore specifico a puntatore #include <stdio.h> int main() { int *ptr; ptr = 1000; *ptr = 5; printf("%d\n", *ptr); } Cosa stampa questo codice? Output del compilatore warning: assignment makes pointer from integer without a cast Pagina 18

Assegnazione di un valore specifico a puntatore L assegnazione di un indirizzo specifico ad una variabile puntatore è da evitare poiché può causare il crash del programma. Pagina 19

Accessi in memoria int i, j = 2, *pt; pt = &j; i = *pt; per ottenere il valore da assegnare a i devono essere fatti 2 accessi in memoria: il primo accesso viene fatto all indirizzo di pt, per recuperare il dato ivi memorizzato, i.e. l indirizzo di j il secondo accesso avviene all indirizzo di j, per recuperare il valore memorizzato nella variabile j Pagina 20

Esempio puntatori Consideriamo gli effetti del seguente codice: int *pointer; int x = 1, y = 2; pointer = &x; y = *pointer; x = pointer; *pointer = 3; // dichiara pointer come un // puntatore a int // (1) assegna a pointer l'indirizzo // di x (i.e., pointer punta x) // (2) assegna a y il contenuto di // pointer // (3) assegna ad x l'indirizzo // contenuto in pointer // (4) assegna alla variabile // puntata da pointer il valore 3 Pagina 21

Diagramma della memoria x 32456 1 x 32456 1 y 54327 2 54327 (1) y 2 12098 pointer = &x; 12098 pointer? pointer 32456 Pagina 22

Diagramma della memoria x 32456 1 x 32456 1 y 54327 2 54327 (2) y 1 12098 y = *pointer; 12098 pointer 32456 pointer 32456 Pagina 23

Diagramma della memoria x 32456 1 x 32456 32456 y 54327 1 54327 (3) y 1 12098 x = pointer; 12098 pointer 32456 pointer 32456 Pagina 24

Diagramma della memoria x 32456 32456 x 32456 3 y 54327 1 54327 (4) y 1 12098 *pointer = 3; 12098 pointer 32456 pointer 32456 Pagina 25

Ricapitolando Possibili valori ottenibili tramite l utilizzo di variabili puntatore: pointer valore della variabile puntatore (i.e., l indirizzo della locazione di memoria a cui punta) &pointer indirizzo fisico della locazione di memoria del puntatore *pointer valore contenuto nella locazione di memoria a cui punta il puntatore Pagina 26

Operazioni sui puntatori A valori di tipo puntatore si applicano le operazioni del tipo int. Particolarmente utile è l operazione di incremento int *pti;... pt++; che consente di puntare alla successiva locazione di tipo int. L uso di queste operazioni verrà approfondito nella Unità 7 Array e Matrici Pagina 27

costanti La specifica const può essere applicata anche a variabili di tipo puntatore. double pi = 3.5; double const *pt = π (*pt)++; // OK (pi vale 4.5) pt++; // NO (pt e costante) In questo caso, la specifica const si applica al puntatore, ma non alla variabile puntata. Pagina 28

a costanti Si può anche specificare che un puntatore debba puntare a costanti. const int k = 3; const int *pt; // dichiarazione di puntatore // a costante pt = &k; // OK pt++; // ammesso anche se non si sa cosa // vada a puntare pt int *pti; pti = &k; // NO Pagina 29

a puntatori Come per ogni altro tipo si può definire un puntatore ad una variabile di tipo puntatore. double x; double * pt; double ** ptpt; x = 4; pt = &x; ptpt = &pt; printf("%f\n", **ptpt); Cosa stampa questo frammento di codice? Pagina 30

Diagramma della memoria stampa il valore di x. Pagina 31

Il puntatore NULL (1/3) Le variabili di tipo puntatore possono assumere anche un valore speciale: NULL Questo valore serve a specificare che la variabile non punta alcuna locazione di memoria. In C tale valore in genere corrisponde allo 0, ma si raccomanda di usare NULL, in particolare per verificare che ad una variabile puntatore non sia associato uno specifico riferimento. NULL è una costante simbolica in genere definita in <stdio.h> Pagina 32

Il puntatore NULL (2/3) Si faccia attenzione a non confondere variabili il cui valore è NULL con variabili non inizializzate: una variabile non inizializzata non ha alcun valore, neanche NULL. Il confronto con NULL può essere usato in una condizione di un istruzione if-else, for, etc. Pagina 33

Il puntatore NULL (3/3) Esempio int *pt = NULL; if (pt!= NULL) *pt = 10; In questo caso il ramo if non viene eseguito. L istruzione *pt = 10; eseguita al momento in cui pt vale NULL genererebbe un errore a tempo di esecuzione. Pagina 34

Il tipo void* (1/2) Mentre nel caso delle dichiarazioni dei tipi primitivi è indispensabile definire il tipo della variabile per consentire al compilatore di allocare la memoria necessaria, nel caso dei puntatori, la memoria per il puntatore è fissa (corrisponde alla dimensione di un indirizzo di memoria) e quindi si può omettere la specifica del tipo della variabile puntata. void *pt; int i; pt = &i; Pagina 35

Il tipo void* (2/2) In questi casi: non sono più ammesse le operazioni sui puntatori il puntatore assegnato ad una variabile void* non può essere assegnato ad una variabile di tipo puntatore (ad un tipo definito). Pagina 36

Conversioni su puntatori Anche nel caso delle variabili di tipo puntatore sono possibili conversioni esplicite: void * pt; int i; pt = &i; int * pti; pti = (int*)pt; // il valore viene convertito // a puntatore a int Tuttavia, l utilizzo delle conversioni sui puntatori è sconsigliato in quanto spesso provoca degli errori di programmazione. Pagina 37

Gestione dinamica della memoria Nell Unità 5 è stato presentato il modello di allocazione della memoria tramite stack, che si basa sulle regole di campo d azione (definito staticamente, cioè al momento della compilazione). Attraverso i puntatori, il C permette di utilizzare un altro modello di allocazione della memoria, che consente di definire la memoria dinamicamente, cioè al momento dell esecuzione del programma. Questa possibilità risulta particolarmente utile ed importante quando non sono note o prevedibili a priori le dimensioni dei dati in ingresso ad un programma. Pagina 38

L operatore sizeof (1/2) Il numero di byte occupati da una variabile è dato dall applicazione di sizeof. Esempio sizeof(a) è il numero di byte occupati dalla variabile a Pagina 39

L operatore sizeof (2/2) L operatore sizeof può essere applicato ad un tipo, ad un nome di variabile o ad una costante Restituisce la dimensione in byte dell oggetto passato come parametro tale calcolo viene effettuato in compilazione in base al tipo di dato che viene passato a sizeof se si incrementa un puntatore p, il suo valore numerico (indirizzo in memoria in byte) verrà incrementato di sizeof(*p) Pagina 40

stampa indirizzo, occupazione di memoria e valore int main (void) { int a = 12; char b = 'a'; float c = 0.1243; printf ("Indirizzo di a e\' %x, occupa %d bytes," " il suo valore e\' %d\n", &a, sizeof(a), a); printf ("Indirizzo di b e\' %x, occupa %d bytes," " il suo valore e\' %c\n", &b, sizeof(b), b); printf ("Indirizzo di c e\' %x, occupa %d bytes," " il suo valore e\' %f\n", &c, sizeof(c), c); return 0; } %x intero esadecimale senza segno Pagina 41

Esecuzione Esercizio 6.1 Si modifichi il codice precedente in modo da stampare la parola byte se l occupazione è pari ad 1, mentre bytes se l occupazione è > 1 Es. Indirizzo di b e' 28ff1b, occupa 1 byte, il suo valore e' a Pagina 42

Differenza tra valore e indirizzo di una variabile L indirizzo è dato in forma numerica (ma non di tipo numerico) ed è assegnato dal compilatore Il valore è assegnato dal programma Tutte le variabili dello stesso tipo occupano lo stesso numero di byte Hanno la medesima rappresentazione interna Pagina 43

Applicazione di sizeof (1/2) Essendo un operatore, sizeof può essere utilizzato ponendo l operando tra parentesi oppure anche senza l utilizzo delle parentesi Le seguenti istruzioni sono equivalenti tra loro: char a = 'r'; int size_a; size_a = sizeof a; size_a = sizeof(a); Pagina 44

Applicazione di sizeof (2/2) Un eccezione a questa possibilità si ha nel caso seguente: int size_float; size_float = sizeof(float); size_float = sizeof float; // espressione // valida // errore in // compilazione quando l operando di sizeof è il nome di un tipo di dato (float, nell esempio), le parentesi sono obbligatorie. Pagina 45

Allocazione dinamica della memoria Durante l esecuzione, un programma può richiedere esplicitamente uno spazio di memoria per immagazzinare dati. Allo stesso modo, può richiedere di rilasciare tale spazio quando non sarà più necessario. Il C offre la funzione malloc per riservare (allocare) uno spazio di memoria e la funzione free per rilasciare (deallocare) memoria. Insieme all operatore sizeof sono essenziali per l allocazione dinamica della memoria. Pagina 46

Funzione malloc La funzione malloc permette di allocare dinamicamente una porzione (chunk) di memoria. void *malloc( size_t size ); Restituisce un puntatore alla porzione di memoria di dimensione size oppure NULL se si è verificato un errore. E definita nella standard library - va inserita la direttiva #include <stdlib.h> size_t è definito come il tipo intero senza segno restituito dall operatore sizeof Pagina 47

Esempio malloc int *p; crea in memoria una variabile di tipo puntatore a int p = malloc(sizeof(int)); crea in memoria una variabile di tipo int restituisce l indirizzo della variabile creata (primo byte) assegna l indirizzo restituito a p *p = 7; la variabile di tipo int creata assume il valore 7 printf("%d", *p); viene stampato a video 7 Pagina 48

Modello di allocazione dinamica L allocazione dinamica della memoria avviene nello heap. Se lo spazio di memoria allocabile dinamicamente è esaurito viene restituito il puntatore NULL. int *pt1; // dichiarazione del puntatore ad int pt1 = malloc(sizeof(int)); // creazione dinamica // della variabile int if (pt1 == NULL) { printf("allocazione fallita\n"); exit(exit_failure); } In caso di mancanza di memoria il programma termina con l istruzione exit(exit_failure); che notifica il fallimento. Pagina 49

Funzione free La funzione free permette di deallocare la memoria allocata dinamicamente. void free( void* ptr ); free dealloca lo spazio puntato da ptr, rendendolo disponibile per usi futuri. Nota: ptr deve essere stato usato in una chiamata precedente a malloc() E definita nella standard library (<stdlib.h>) Pagina 50

Esempio free #include <stdio.h> #include <stdlib.h> int main() { int *p; double *d; p = malloc(sizeof(int)); *p = 7; printf("%d", *p); free(p); d = malloc(sizeof(double)); *d = 7; printf(" %f", *d); free(d); } Pagina 51

Esercizi Esercizio 6.2 Scrivere un programma che legga 10 numeri interi e restituisca il minimo, usando variabili di tipo puntatore ad int anziché variabili di tipo int. Esercizio 6.3 Scrivere il programma dell esercizio precedente tramite allocazione dinamica della memoria. Deallocare la memoria utilizzata prima della terminazione del programma. Pagina 52

Esercizi Esercizio 6.4 Scrivere una funzione che dato in ingresso un puntatore ne stampi la dimensione in byte, il valore, l indirizzo di memoria ed il valore della variabile puntata. Scrivere un programma che ne verifichi il comportamento. Pagina 53