Anteprima
Vedrai una selezione di 9 pagine su 39
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 1 Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 2
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 6
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 11
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 16
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 21
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 26
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 31
Anteprima di 9 pagg. su 39.
Scarica il documento per vederlo tutto.
Riassunto esame Fondamenti di Informatica: Manuale di C/C++, prof. Dragoni Pag. 36
1 su 39
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

Puntatore a puntatore

Un tipo puntatore può puntare anche ad un altro puntatore. Per dichiarare tale puntatore si usano

due asterischi.

Ad es

int i=100;

int* ptr1=&i;

int** ptr2=&ptr1;

ptr1 e ptr2 sono due puntatori diversi, ma il primo è puntatore a interi e punta i, il secondo è

puntatore a puntatore di interi e punta ptr1. Per deferenzare il puntatore di puntatori si possono

usare i due asterischi: **ptr2=95 (assegna 95 a i)

Puntatori e array

In C++ gli array sono implementati mediante puntatori. Il nome di un vettore è esattamente un

puntatore al primo elemento dell'array. Prendendo ad esempio il vettore gradi[3],

cout << gradi[0] visualizzerà il primo elemento dell'array, ma lo farà anche cout << *gradi,

perché il nome gradi è un puntatore al primo elemento. In più se incrementiamo il puntatore a un

valore pari a un indice del vettore e poi lo referenziamo, andiamo a prendere l'elemento del

vettore corrispondente a quell'indice.

Pertanto per leggere o scrivere un elemento di un array si possono utilizzare indifferentemente

entrambe le notazioni, quella vettoriale e quella basata sui puntatori. Il nome di un array è però

una costante puntatore, non una variabile, non si può cambiarne il valore. Tuttavia, è possibile

cambiare i valori delle variabili di tipo puntatore per farle puntare valori differenti in memoria.

Array di puntatori

Se bisogna definire parecchi puntatori a uno stesso tipo si può utilizzare un array di puntatori. Un

array di puntatori è un vettore i cui elementi sono puntatori dello stesso tipo: int* ptr[10] definisce

10 puntatori ad interi. Ogni elemento contiene un indirizzo che punta ad altre variabili di tipo

intero in memoria e può essere riassegnato.

Queste due definizioni sono equivalenti:

char stringa[] = “Ciao vecchio mondo”;

char* stringa = “Ciao vecchio mondo”;

Puntatori a stringhe

Definisco una stringa di caratteri: char alfabeto[27]=”ABCD…..”;

Dichiaro p puntatore a chiar: char* p;

Faccio puntare p al primo carattere di alfabeto scrivendo: p=alfabeto; o p=&alfabeto[0];

Posso anche assegnare: p=alfabeto+15; o p=&alfabeto[15];

Non posso assegnare: p=&alfabeto; perchè p e alfabeto sono puntatori al tipo char e l’istruzione

tenterebbe di assegnare a p l’indirizzo di un puntatore a char e non l’indirizzo di una variabile di

tipo char.

Aritmetica dei puntatori

Se un puntatore a un tipo T viene incrementato (o decrementato) di 1, il suo valore viene in realtà

incrementato (o decrementato) di un numero pari alla dimensione del tipo T espressa in byte. In

generale, incrementare o decrementare di un intero n un puntatore significa incrementarlo o

decrementarlo di un numero di byte pari a n moltiplicato per la dimensione del tipo puntato.

Ad es: int gradi[5] = (10, 20, 30, 40, 50);

p=gradi;

p punta al primo intero 10 in gradi; ma dopo l’istruzione p++ p punterà al secondo intero 20.

Poichè ogni elemento occupa 4 byte, p è stato incrementato di 4 e non di 1.

Si può quindi usare tale tecnica per attraversare un vettore senza usare una variabile di indice.

Se il vettore da attraversare è una stringa, si può semplificare il ciclo considerando il fatto che

essa termina con il carattere nullo:

char messaggio[] = “Ciao vecchio mondo”;

p = messaggio;

while (*p) cout << p++ << endl;

Il ciclo while si ripete finchè *p ha un valore diverso da zero; si stampa il carattere e si

incrementa p per puntare al successivo carattere.

I puntatori possono anche essere sottratti, ma non sommati, moltiplicati o divisi.

Puntatori costanti e puntatori a costanti

Il nome di un array è un puntatore costante: il suo valore non può cambiare, ma possono essere

cambiati i valori della variabile puntata.

Un puntatore a costante potrà cambiare il suo valore ma non quello della variabile a cui punta.

Per creare un puntatore costante si utilizza il formato:

tipo_di_dato* const nome_punt = indirizzo_variabile

Si può scrivere: *p1=e ma non p1=&e

Per definire un puntatore a costante si usa il formato:

const tipo_di_dato* nome_puntatore = indirizzo_const_o_stringa;

Si può scrivere: p1=&e ma non *p1=15, qualunque tentativo di modificare il contenuto della

posizione di memoria puntata da p1 provocherà errore.

Nota: La definizione di un puntatore costante ha la parola riservata const davanti al nome del

puntatore, mentre il puntatore a una costante ha la parola riservata const davanti al tipo di dato.

Per definire puntatori costanti a costanti si usa il seguente formato:

const tipo_di_dato *const nome_puntatore = indirizzo_const_o_stringa

Se si sa che un puntatore punterà sempre la stessa posizione e non dovrà mai essere riallocato

lo si definisce come puntatore costante. Se si sa che il dato puntato dal puntatore non dovrà mai

essere modificato si definisce come puntatore a costante.

Lo spazio non è significativo nella dichiarazione di puntatori. Le dichiarazioni seguenti sono

equivalenti:

int* p;

int * p;

int *p;

Puntatori come argomenti di funzioni

Spesso si vuole che una funzione restituisca più di un valore oppure modifichi variabili passate

come argomenti. Si possono ottenere questi risultati passando puntatori, magari nomi di vettori,

come argomenti attuali.

Il passaggio per riferimento è più efficiente del passaggio per indirizzo

Puntatori a funzioni

E’ possibile creare anche puntatori a funzioni; anzichè indirizzare dati, i puntatori di funzioni

indirizzano codice eseguibile, dato che anche le istruzioni stanno in memoria in certi indirizzi. In

C++ si possono quindi assegnare gli indirizzi iniziali di funzioni a puntatori. Tali funzioni si

possono chiamare in modo indiretto tramite un puntatore il cui valore è uguale all’indirizzo iniziale

della funzione in questione. La sintassi generale per la dichiarazione di un puntatore a funzione

è:

tipo_di_ritorno (*puntatore_funzione) (argomenti);

Questo formato dice al compilatore che puntatore_funzione è un puntatore a una funzione che

restituisce il tipo_di_ritorno e una lista di parametri.

Un puntatore a una funzione è semplicemente un puntatore il cui valore è l’indirizzo del nome

della funzione. Dato che il nome di una funzione è un puntatore, come il nome di un vettore, un

puntatore a una funzione è un puntatore a un puntatore costante.

La sintassi generale per inizializzare un puntatore a funzione è:

puntatore_funzione = nome_di_una_funzione

La funzione assegnate deve avere il tipo del ritorno e dei parametri appropriati al tipo del

puntatore a funzione; in caso contrario, si produrrà un errore di compilazione.

I puntatori a funzioni permettono anche di passare una funzione come argomento a un’altra

funzione, specificandone il nome.

Funzione qsort() (Quicksort per ordinare vettori)

Presente nella libreria search. Ha come parametri:

(void*) vettore → Array da ordinare;

(size_t) 10 → Numero di elementi dell’array

sizeof(int) → Dimensione in byte di ciascun elemento dell’array

Array di puntatori di funzioni

Certe applicazioni richiedono di scegliere una funzione fra tante, in base alla valutazione a

run­time di determinare condizioni. Un metodo è quello di usare un’istruzione switch con

parecchi case. Un’altra soluzione è quella di utilizzare un array di puntatori di funzione. Si può

selezionare una funzione della lista e chiamarla.

Sintassi generale:

tipoRitorno(*PuntatoreFunz[LunghezzaArray]) (argomenti);

Si può assegnare l’indirizzo delle funzioni all’array, fornendo le funzioni che sono già state

dichiarate.

Puntatori a strutture

Un puntatore può anche puntare una strutture. Dati un tipo struct e una variabile di questo tipo, si

può definire un puntatore a questo tipo struct e inizializzarlo in maniera che punti alla variabile.

Per riferirsi a una variabile della struct tramite un puntatore è necessario mettere le parentesi

tonde del tipo (*p).nome; Per non utilizzare tale notazione è stata introdotta la notazione freccia a

destra; l’istruzione precedente è equivalente a p­>nome;

Gestione dinamica della memoria

Con il termine heap si denota la parte della memoria principale che può essere allocata

dinamicamente durante l'esecuzione del programma. Per poter essere riallocara può essere

deallocata automaticamente mediante un garbage recollector oppure rimanere occupata fino a

che il programmatore la libera esplicitamente mediante opportune istruzioni. In C la gestione

della memoria dinamica avviene tramite le funzioni malloc, calloc e free. In C++ esistono gli

operatori new e delete.

Il sistema operativo assegna al programma specifici segmenti della memoria principale: il code

segment (ospita il codice), il data segment (ospita costanti e variabili globali), lo stack (contiene

le variabili locali, i parametri delle funzioni e le copie dei registri per restituire il controllo alle

funzioni chiamanti al termine delle funzioni chiamate). La memoria rimasta nello stack, lo heap,

viene usata per allocare dinamicamente le variabili.

Gli operatori new e delete sono più affidabili di quelli del C perché allocano memoria in funzione

del tipo di dato da memorizzare ed effettuano ogni volta i relativi controlli.

L'operatore new

Genera dinamicamente una variabile di un certo tipo, assegnando un blocco di memoria della

dimensione di quel tipo. L'operatore restituisce un puntatore che contiene l'indirizzo del blocco di

memoria allocato, cioè della variabile. La variabile sarà accessibile deferenziando il puntatore.

La sintassi è:

tipo* puntatore = new tipo

tipo* puntatore = new tipo[dimensione] (se array)

Dove puntatore sta per il nome a cui si assegna l'indirizzo dell'oggetto generato. Nel secondo

fattore al puntatore si assegna l'indirizzo di memoria di un blocco sufficientemente grande per

contenere un array con dimensione elementi di tipo.

Se il puntatore è già stato definito si può semplicemente usare new per assegnargli la variabile

dinamica:

int* pi;

pi = new int;

L'effetto è sempre quello di creare una variabile intera senza nome, accessibile deferenziando il

puntatore pi.

Se nell'heap esiste un blocco della dimensione richiesta, new restituisce un puntatore al primo

byte del blocco, altrimenti restituisce 0 o NULL.

La dimensione del blocco può anche essere allocata in runtime, richiedendola all'input.

L'heap non è infinito e se lo spazio finisce, new restituisce 0 o NULL e quindi non dà errore!

L�

Dettagli
Publisher
A.A. 2013-2014
39 pagine
1 download
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher henry0894 di informazioni apprese con la frequenza delle lezioni di Fondamenti di informatica e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università Politecnica delle Marche - Ancona o del prof Dragoni Aldo Franco.