• Non ci sono risultati.

Programmazione Procedurale in Linguaggio C++

N/A
N/A
Protected

Academic year: 2021

Condividi "Programmazione Procedurale in Linguaggio C++"

Copied!
25
0
0

Testo completo

(1)

G. Mecca – Università della Basilicata – mecca@unibas.it

Programmazione Procedurale in Linguaggio C++

Tipi Strutturati Concetti Avanzati

versione 2.5

Questo lavoro è concesso in uso secondo i termini di una licenza Creative Commons (vedi ultima pagina)

Sommario

m

Tipi Riferimento

m

Tipi Puntatore

ðValori per un Puntatore

ðDereferenziazione di un Puntatore

m

Puntatori e Riferimenti

m

Passaggio dei Parametri

ðPuntatori e Array

Tipi Strutturati: Concetti Avanzati >> Sommario

(2)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 3

Tipi Riferimento

m

Parametro per riferimento

ðparametro che riceve come valore un

“riferimento” all’argomento

m

Riferimento ad un dato

ðintermediario tra il processore e il dato ðha come valore l’indirizzo di memoria del

dato

ðqualsiasi operazione effettuata sul

riferimento viene effettuata in realtà sul dato

4

Tipi Riferimento

m

In effetti

ði riferimenti in C++ possono essere utilizzati anche al di fuori del passaggio dei parametri ðper esempio è possibile dichiarare variabili

che sono riferimenti ad altri dati

ðe quindi possono essere utilizzate come intermediari per utilizzare i dati in questione

Tipi Strutturati: Concetti Avanzati >> Tipi Riferimento

(3)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 5

Tipi Riferimento

m

Di che tipo sono le var. riferimento ?

ði riferimenti sono “tipati”: ogni riferimento può essere intermediario per dati di un solo tipo ðes: riferimento a intero, riferimento a stringa

ecc.

m

Tipo riferimento

ðdato un tipo T, il tipo dei riferimenti a dati di tipo T è T&

ðes: int&, char&, float& ...

Tipi Riferimento

m

Valore per un riferimento

ðoperazione di assegnazione ordinaria ða destra deve esserci il dato a cui riferirsi ðil dato deve essere del tipo opportuno ðil riferimento viene “legato” al dato

m

Esempio

ðchar c;

ðchar& rif = c;

ðstring& rif2 = c; // errore

Tipi Strutturati: Concetti Avanzati >> Tipi Riferimento

(4)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 7

Riferimenti: Un Esempio

#include <iostream.h>

void main() { int x;

int& rif = x;

x = 1;

cout << "Valore di x: " << x << endl;

cout << "Valore di rif: " << rif << endl;

rif++;

cout << "Valore di rif dopo l'incr.:" << rif << endl;

cout << "Valore di x dopo l'incr.: " << x << endl;

}

>> riferimenti.cpp Valore di x: 1

Valore di rif: 1 Valore di rif dopo l’incr.: 2 Valore di x dopo l’incr.: 2

rif è un riferimento a x (intermediario per x)

le operazioni su rif

sono in realtà effettuate su x

8

Tipi Riferimento

m

Note sui riferimenti

ðdevono essere necessariamente inizializzati alla dichiarazione

ðint& rif; // errore sintattico ðint& rif = x; // OK

ðda quel momento in poi sono intermediari per il dato a cui sono stati legati

ðint x, y;

ðint& rif = x;

ðrif = y; // assegna a x il valore di y

Tipi Strutturati: Concetti Avanzati >> Tipi Riferimento

(5)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 9

Tipi Riferimento

m

In altri termini

ðun riferimento deve essere inizializzato alla dichiarazione legandolo ad un dato del tipo opportuno

ðnon possono esistere riferimenti “indefiniti”

ðda quel momento in poi il riferimento è un intermediario per il dato a cui è stato legato ðe non può essere legato ad alcun altro dato

Tipi Riferimento

m

Utilizzo dei riferimenti

ðin sostanza esclusivamente per il passaggio dei parametri per riferimento

m

Semantica reale dei par. per riferimento

ðun par. per riferimento è un parametro di un

tipo riferimento

ðal passaggio dei parametri viene legato all’argomento

ðdiventa un intermediario per l’argomento

Tipi Strutturati: Concetti Avanzati >> Tipi Riferimento

(6)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 11

Tipi Puntatore

m

Una delle caratteristiche del C/C++

ðconsentire al programmatore di gestire direttamente i registri della memoria ðovvero senza passare per le variabili e i

parametri

m

Compromesso tra vantaggi e svantaggi

ðefficienza (delle operazioni sono più rapide) ðpoca sicurezza (il codice diventa più fragile)

12

Tipi Puntatore

m

Lo strumento per farlo

ði puntatori

m

Puntatore

ðdato il cui valore corrisponde all’indirizzo di un altro dato (variabile, parametro, costante) ðil puntatore “punta” allo spazio di memoria

del dato

ðattraverso il puntatore è possibile manipolare il dato puntato

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(7)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 13

Tipi Puntatore

m ATTENZIONE

ðpuntatori e riferimenti: ci sono delle analogie ma sono concetti diversi

m In sintesi, per ora:

ðun riferimento è un intermediario gestito direttamente dal processore (utilizzo trasparente)

ðun puntatore può essere utilizzato come

intermediario, ma è il programmatore a doverlo fare ði puntatori sono stati pensati principalmente per altri

scopi (gestire direttamente la memoria)

Tipi Puntatore

m

Puntatori e tipi di dato

ðcome i riferimenti, anche i puntatori sono

“tipati”: ciascun puntatore può contenere l’indirizzo di dati di un solo tipo

ðes: puntatore a interi, puntatori a caratteri ...

m

Tipo puntatore

ðdato un tipo T, il tipo dei puntatori a dati di tipo T è T*

ðes: int*, char*, float* ...

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(8)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 15

Valori per un Puntatore

m

Valori ammissibili per un puntatore

ðil valore di qualsiasi indirizzo della memoria

m

Inoltre

ðai puntatori sono applicabili liberamente gli operatori aritmetici

m

Esempio

char* p; p = (char*) 1000;

p = p + 1;

p = p – 3;

p = p * 2;

assegna a p il valore del registro (p “punta” al registro 1000); il cast è necessario perché 1000 è una costante di tipo int

16

Valori per un Puntatore

m

Inoltre

ðattraverso il puntatore è possibile cambiare il valore dei registri di memoria

m

Esempio

void main() { char* p;

p = (char*) 1000;

*p = 1; // dereferenziazione >>

}

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

>> puntatori.cpp

ATTENZIONE: questo codice è sintatticamente corretto ma logicamente scorretto

(9)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 17

Valori per un Puntatore

m

Il problema dei puntatori

ðla gestione diretta della memoria provoca facilmente errori di sconfinamento

ðtentativo di utilizzare zone di memoria non assegnate al programma (con gravi errori)

m

Utilizzo “corretto” dei puntatori

ðsolo per la manipolazione di zone di memoria assegnate ai dati del programma

ðcostanti, variabili, parametri

Valori per un Puntatore

m

Valori corretti per un puntatore

ðindirizzi di memoria di dati del programma

m

Due modi possibili

ðmodo n.1 chiedere l’indirizzo di un dato (variabile, parametro, costante) già dichiarato ðmodo n. 2 chiedere di assegnare un nuovo

spazio al programma e utilizzare l’indirizzo

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(10)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 19

Valori per un Puntatore

m

Modo n. 1

ðindirizzi di memoria di dati del programma ðottenibili a partire dai dati in questione

attraverso l’operazione di “referenziazione”

m

Operatore di “referenziazione”: &

ðapplicato ad un dato, restituisce il suo indirizzo di memoria

ðanche detto “operatore di indirizzo”

ðes: int x; int* p; p = &x; p “punta” a x ...

#1500 xxx

...

#1502 p

#1501 x

#1500

20

Valori per un Puntatore

m

Modo n. 2

ðindirizzo di un nuovo spazio di memoria ðè possibile chiedere un nuovo spazio con

l’operatore new

ðe poi rilasciarlo con l’operatore delete

m

Esempio:

float* p;

ðp = new float;

ð... // operazioni su p ðdelete p;

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

...

... ...

xxx ...

xxx

#2500 ... ...

#1500 p #2500

*p

attribuisce al programma un nuovo spazio di memoria e ne assegna l’indirizzo a p

(11)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 21

Valori per un Puntatore

m

Semantica di new <tipo>

ðattribuisce al programma un nuovo spazio di memoria del tipo specificato

ðrestituisce l’indirizzo del nuovo spazio

m

Semantica di delete p

ðlibera lo spazio di memoria puntato da p ðal termine il valore di p è indefinito (come

quello di un puntatore non inizializzato)

Valori per un Puntatore

m Attenzione

ðsi tratta di un meccanismo del tutto nuovo

m Finora

ðla memoria veniva attribuita al programma solo sulla base delle dichiarazioni

ðche erano stabilite a tempo di compilazione

m Con new e delete

ðposso richiedere e rilasciare memoria a tempo di esecuzione

ðè lo strumento che viene utilizzato per costruire strutture dinamiche (>>)

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(12)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 23

Valori per un Puntatore

m

Inoltre

ðla memoria attribuita al programma attraverso l’istruzione new NON viene allocata nella pila di attivazione

ðviene utilizzata una nuova zona di memoria

m

Heap (“Mucchio”)

ðzona di memoria riservata all’utilizzo dinamico della memoria con new e delete

24

Valori per un Puntatore

m

Un valore speciale per i puntatori: NULL

ðriferimento “nullo”

ðquando un puntatore assume il valore NULL

“non punta a nessun registro della memoria”

m

Esempio

ðint* p;

ðp = NULL;

m

In alternativa

ðp = 0; // 0 e NULL sono equivalenti

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(13)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 25

Dereferenziazione di un Puntatore

m

Come utilizzare il dato puntato da un puntatore ?

ðattraverso un opportuno operatore applicato al puntatore

ðoperatore di “dereferenziazione”

m

Operatore di “dereferenziazione”: *

ðoperatore che, applicato ad un puntatore,

consente di lavorare sullo spazio di memoria puntato dal puntatore

Dereferenziazione

m

Esempio:

char c;

char* p;

p = &c;

m

In questo caso

ð*pfa rappresenta lo spazio di memoria puntato da p (cioè lo spazio di c)

ðè possibile utilizzarlo come un qualsiasi altro dato nelle istruzioni

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(14)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 27

Un Esempio

#include <iostream.h>

void main() { char c;

char* p;

p = &c;

*p = 'a';

cout << "Valore di c: " << c << endl;

cout << "Valore di p: " << (int)p << endl;

cout << “Valore di *p: “ << *p << endl;

}

>> puntatori2.cpp Valore di c: a

Valore di p: 2500 Valore di *p: a

p “punta” a c (il valore di p è l’indirizzo di c)

*p rappresenta lo spazio di memoria di c

...

#2500

‘a’

...

#2502 p

#2501 c

#2500

28

Dereferenziazione

m Attenzione

ðil puntatore nullo (NULL) non può essere dereferenziato

ðsi tratta di un grave errore logico

m Nota

ða differenza dei puntatori, i riferimenti del C++ non possono essere nulli

ðdevono essere necessariamente inizializzati alla dichiarazione

ðma in linea di principio avrebbe senso avere anche riferimenti nulli

Tipi Strutturati: Concetti Avanzati >> Tipi Puntatore

(15)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 29

Puntatori e Riferimenti

m

Puntatori e riferimenti

ðmolte analogie, alcune differenze sostanziali

m

In sintesi

ðnella sostanza, sono due strumenti diversi per fare le stesse cose

ðqualunque cosa si possa fare con i puntatori si può fare anche con i riferimenti

ðma ciascuno ha un utilizzo privilegiato

Puntatori e Riferimenti

m

Puntatore e riferimento: analogia

ðentrambi hanno come valore l’indirizzo di memoria del dato

Tipi Strutturati: Concetti Avanzati >> Puntatori e Riferimenti

void main() { char c;

char& rif = c;

...

}

void main() { char c;

char* p = &c;

...

}

...

#2500 xxx

...

valori di tipo char&

valori di tipo char

...

#2502 rif

#2501 c

#2500

...

#2500 xxx

...

valori di tipo char*

valori di tipo char

...

#2502 p

#2501 c

#2500

(16)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 31

Puntatori e Riferimenti

m

Puntatore e riferimento: differenza

ðil riferimento è un intermediario “automatico”:

qualsiasi operazione sul riferimento viene automaticamente effettuata sul dato

ðil puntatore può essere utilizzato come se fosse un intermediario, ma il programmatore deve manipolare esplicitamente la memoria ðusando l’operatore di dereferenziazione

32

Puntatori e Riferimenti

m

Nell’esempio precedente

Tipi Strutturati: Concetti Avanzati >> Puntatori e Riferimenti

void main() { char c;

char& rif = c;

rif = ‘a’;

}

void main() { char c;

char* p = &c;

*p = ‘a’;

}

...

#2500 xxx

...

valori di tipo char&

valori di tipo char

...

#2502 rif

#2501 c

#2500

...

#2500 xxx

...

valori di tipo char*

valori di tipo char

...

#2502 p

#2501 c

#2500

‘a’ ‘a’

(17)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 33

Puntatori e Riferimenti

m

Ricapitolando

ðabbiamo introdotto due nuovi categorie di tipi: tipi riferimento e tipi puntatore

ðabbiamo introdotto due nuovi operatori:

operatore di indirizzo (&), operatore di dereferenziazione (*)

m

Utilizzo di & e *

ðdue funzioni diverse per ciascun simbolo ðattenzione a non fare confusione

Puntatori e Riferimenti

Tipi Strutturati: Concetti Avanzati >> Puntatori e Riferimenti

operatore di dereferenz.:

serve ad utilizzare lo spazio di memoria puntato dal dato (che deve essere un puntatore)

es: *p = ‘x’;

operatore di indirizzo:

restituisce l’indirizzo di memoria del dato (parametro, costante, variabile)

es: char* p = &c;

Prima di un dato

definisce un tipo puntatore es: char* p;

definisce un tipo riferimento es: int& rif = x;

Dopo un tipo

*

&

(18)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 35

Puntatori e Riferimenti

m Riferimenti

ðvengono dichiarati di tipo riferimento

(utilizzo di & nella dichiarazione dopo il tipo) ðvengono utilizzati come dati ordinari

(senza bisogno di & né * nelle istruzioni)

m Puntatori

ðvengono dichiarati di tipo puntatore

(utilizzo di * nella dichiarazione dopo il tipo) ðper assegnargli un valore si usa &

ðper utilizzare lo spazio di memoria si usa *

36

Puntatori e Riferimenti

m

Utilizzo principale dei riferimenti

ðpassaggio dei parametri per riferimento

m

Utilizzi principale dei puntatori

ðcostruire strutture di dati “collegate” di carattere dinamico

ðes: rappresentazione collegata per le liste ðne parleremo più avanti (>>)

Tipi Strutturati: Concetti Avanzati >> Puntatori e Riferimenti

(19)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 37

Puntatori e Riferimenti

m

Ma

ði due tipi di dato sono in pratica sostituibili

m

In particolare

ði puntatori possono essere utilizzati per

simulare il pass. per riferimento nei linguaggi in cui ci sono solo par. per valore (es: C) ði riferimenti possono essere utilizzati per

costruire strutture collegate nei linguaggi senza gestione della memoria (es: Java)

Passaggio dei Parametri

m

In C++

ðparametri standard (di tipo ordinario)

ðparametri per riferimento (di tipo riferimento)

m

Ma

ðesistono linguaggi in cui non esistono i tipi riferimento

ðesempio: il linguaggio C

ðin questi linguaggi: solo parametri standard ðcome è possibile modificare gli argomenti ?

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

(20)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 39

Passaggio dei Parametri

m

Soluzione

ðsi utilizzano i tipi puntatore

m

Idea

ðil parametro viene dichiarato di tipo puntatore ðl’argomento che viene passato è l’indirizzo

del dato da modificare

ðnel sottoprogramma il puntatore viene dereferenziato per utilizzare il dato

ðcioè: il puntatore è usato come intermediario

40

Passaggio dei Parametri

m

Un esempio semplice

ðun programma che scambia il valore di due variabili

ðun sottoprogramma per lo scambio

m

Scambio di due valori x e y

ðuso un terzo valore, z

ðassegno il valore di x a z ðassegno il valore di y a x ðassegno il valore di z a y

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

III passo II passo I passo v. iniziali Esempio

5 5 10

5 10 10

5 10 5

xxx 10 5

z y x

(21)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 41

Passaggio dei Parametri

m

Nota

ðse non utilizzassi la variabile z non potrebbe funzionare

m

Esempio

ðassegno il valore di x a y ðassegno il valore di y a x ðanalogamente se faccio il

contrario

II passo I passo v. iniziali Esempio

5 5

5 5

10 5

y x

Passaggio dei Parametri

#include <iostream.h>

void scambia (int& x, int& y);

void main() { int a, b;

cout << "Immetti il valore di a: "; cin >> a;

cout << "Immetti il valore di b: "; cin >> b;

scambia(a, b);

cout << "Valore di a dopo lo scambio: " << a << endl;

cout << "Valore di b dopo lo scambio: " << b << endl;

}

void scambia (int& x, int& y) { int z;

z = x;

x = y;

y = z;

return;

}

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

>> scambio1.cpp

(22)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 43

Puntatori e Array

m

Una particolarità del C++

ðil passaggio dei parametri di tipo array ðfinora considerata una eccezione

m

In realtà

ðsi tratta di un passaggio di parametri basato su puntatori

ðper via della particolare natura degli array in C/C++

44

Puntatori e Array

m

Array

ðzona di memoria di variabili dello stesso tipo ðpiù una variabile aggiuntiva: la variabile array

m

Variabile array

ðpuntatore alla zona di memoria dell’array

m

Parametro array

ðparametro di tipo puntatore

ðil parametro viene dereferenziato con []

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

(23)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 45

Puntatori e Array

m

In effetti, in C/C++

ði tipi array e i tipi puntatori sono strettamente legati e di fatto intercambiabili

ðper ogni tipo T, T* e T[] sono equivalenti es: int* e int[]

ðle parentesi quadre sono operatori di dereferenziazione

ðse x è un array: x[i] = *(x + i)

Puntatori e Array

m

Esempio:

float temp[N];

ðla variabile array temp è di tipo float*

ðtemp[0]è equiv a *temp (la prima variabile dell’array)

ðtemp[1]è equiv a *(temp + 1) (la seconda variabile dell’array)

ðtemp[2]è equiv a *(temp + 2) (la terza variabile dell’array) ð...

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

(24)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 47

Puntatori e Array

m

Di conseguenza

ðtutto quello che il sottoprogramma ha

bisogno di conoscere è il puntatore all’array ðnon è indispensabile che conosca la

dimensione dell’array

ðnon vengono fatti controlli sullo sconfinamento

ðdi conseguenza non è indispensabile specificare la dimensione di un par. array

48

Esempio: Le Temperature

#include <iostream.h>

const int N = 12;

void leggi (float temp[N]);

void stampa (float temp[N]);

void main() {

float temperature[N];

leggi (temperature);

stampa (temperature);

...

}

Tipi Strutturati: Concetti Avanzati >> Passaggio dei Parametri

prototipi equivalenti:

void leggi (float* temp);

void stampa (float* temp);

void leggi (float temp[]);

void stampa(float temp[]);

>> temperature3.cpp

(25)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 49

Riassumendo

m

Tipi Riferimento

m

Tipi Puntatore

ðValori per un Puntatore

ðDereferenziazione di un Puntatore

m

Puntatori e Riferimenti

m

Passaggio dei Parametri

ðPuntatori e Array

Termini della Licenza

m This work is licensed under the Creative Commons Attribution- ShareAlike License. To view a copy of this license, visit

http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Termini della Licenza

m Questo lavoro viene concesso in uso secondo i termini della licenza “Attribution-ShareAlike” di Creative Commons. Per ottenere una copia della licenza, è possibile visitare

http://creativecommons.org/licenses/by-sa/1.0/ oppure inviare una lettera all’indirizzo Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Riferimenti

Documenti correlati

Obiettivo: contribuire anche a livello generale a realizzare la maggior protezione di tutte le acque dall'inquinamento da nitrati riducendo l'impatto ambientale dell'attività

ðpasso 2.2.4: analizza il tentativo e stampa l’esito Sottoprogrammi: Metodologia di Sviluppo &gt;&gt; Indovina il Numero.. Mecca - Programmazione Procedurale in Linguaggio

Sottoprogrammi: Metodologia di Sviluppo &gt;&gt; Tecniche di Test e

ðDefinizione di Funzioni ðDefinizione di Procedure ðChiamata di Funzioni ðChiamata di Procedure ðPassaggio dei Parametri ðProgrammazione Modulare. Termini

Strutture di Dati: Lista &gt;&gt; Rappresentazione con Record e Array. ATTENZIONE ai

Strutture di Dati: Lista &gt;&gt; Inserimenti e Cancellazioni. Mecca - Programmazione Procedurale in Linguaggio

Strutture di Dati: Lista &gt;&gt; Gestione dei File. i conta il numero di valori prelevati dal

ðes: la lista contiene almeno 3 numeri negativi; conto i numeri &lt; 0; al termine verifico se sono almeno 3 ðes: tutti i numeri sono compresi tra 1 e 90. conto i numeri tra 1 e 90