• Non ci sono risultati.

Sono variabili il cui valore corrisponde ad un indirizzo di memoria Puntatori

N/A
N/A
Protected

Academic year: 2021

Condividi "Sono variabili il cui valore corrisponde ad un indirizzo di memoria Puntatori"

Copied!
32
0
0

Testo completo

(1)

Sono variabili il cui valore corrisponde ad un indirizzo di memoria

Puntatori

(2)

Dichiarazione di variabile puntatore

• Esistono puntatori per ogni tipo di variabile puntata

– Un dato puntatore può puntare solo a un determinato tipo di variabili, quello specificato nella dichiarazione

• Si usa il qualificatore di tipo (suffisso) *

– Es. : int* pointer; (ma anche int *pointer)

– dichiara la variabile pointer, puntatore ad una qualunque variabile di tipo int

(3)

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)

(4)

Operatore di indirizzo &

Es.:

&a ammesso

&(a+1) non ammesso

&a = b non ammesso

Perché? (in quanto 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)

(5)

Assegnazione di valore a un puntatore

NON si possono assegnare valori a un puntatore, salvo che in questi tre casi:

1. a un puntatore é assegnato il valore NULL (non punta a

“niente”)

2. a un puntatore è assegnato l’indirizzo di una variabile esistente, restituito dall’operatore &

( Es. int a; int* p; p=&a; )

3. é eseguita un’operazione di allocazione dinamica della

memoria

(6)

L’operatore di dereferenziazione *

Consideriamo int y=5;

int *yPtr;

yPtr = &y;

(7)

Operazioni sui puntatori

Operazioni fondamentali:

Assegnazione di valore (indirizzo) ad un puntatore int* pi = &i p = q

Riferimento all’oggetto puntato *pi=3

Confronto tra puntatori (==, !=)

(8)

Operazioni sui puntatori

E’ possibile specificare che un dato puntatore non deve essere usato per modificare l’oggetto puntato attraverso la parola chiave const:

int i;

const int* p=&i;

Le istruzioni in cui si usa p per aggiornare i vengono segnalate

come erronee

(9)

L’operatore di dereferenziazione *

L’operatore unario di dereferenziazione * di un puntatore restituisce il valore della variabile puntata dall’operando:

come r-value, esegue un’operazione di estrazione

Es.: a = *p; assegna ad a il valore della variabile puntata da p come l-value, esegue un’operazione di inserimento

Es.: *p = a; assegna il valore di a alla variabile puntata da p

(10)

L’operatore di dereferenziazione *

l’operazione di deref. é inversa a quella di indirizzo.

Se assegniamo a un puntatore p l’indirizzo di una variabile a,

p = &a;

allora

*p == a

cioè la deref. di p coincide con a

(11)

L’operatore di dereferenziazione *

ATTENZIONE: non é detto il contrario !!!

se si assegna alla deref. di p il valore di a,

*p = a ;

ciò non comporta automaticamente che in p si ritrovi l’indirizzo

di a, ma semplicemente che il valore della variabile puntata da p

coinciderà con a

(12)

Attenzione!

la dichiarazione di un puntatore comporta allocazione di memoria per la variabile puntatore, ma non per la variabile puntata.

Es.: int* lista;

alloca memoria per lista ma non per la variabile puntata da

lista

(13)

Array e puntatori

Il nome di un array è in realtà un puntatore costante all’indirizzo di partenza dell’array stesso, per cui non può essere modificato nelle operazioni di aritmetica dei puntatori.

I puntatori possono essere utilizzati in tutte le

operazioni di indicizzazione di un array

(14)

Array e puntatori

La dichiarazione di un array comporta allocazione di memoria di una variabile puntatore (il nome dell’array), e dell’area puntata, di lunghezza predefinita

il puntatore é dichiarato const e inizializzato con l’indirizzo dell’area puntata (cioè del primo elemento dell’array)

Es.: int lista[5];

• alloca memoria per il puntatore costante lista;

• alloca memoria per 5 valori di tipo int;

• inizializza lista con &lista[0]

(15)

Array e puntatori (1)

Il nome (usato da solo) di un array ha il significato di puntatore al primo elemento dell’array

Ogni altro elemento é accessibile tramite la deref. del puntatore-array incrementato di una quantità pari all’indice/offset dell’elemento ovvero le espressioni (dato un array A):

A[i] e *(A+i)

conducono ad identico risultato anche se sono due formalismi

diversi.

(16)

Array e puntatori (2)

Se A[N] è un array di indirizzo ind,

A[i] il suo elemento i-esimo (i intero),

l’indirizzo di A[i] sarà dato dall’espressione

*(ind+i)

(17)

C funzioni

à

argomenti

passaggio dei parametri per riferimento (per indirizzo): come parametro della funzione viene passato l’indirizzo di una variabile

• L’argomento deve essere di tipo puntatore al tipo del dato su cui si opera

• L’argomento (il suo nome) si comporta come un sinonimo (alias) del corrispondente parametro passato

Record di attivazione a

b

Indirizzo di rientro in foo

...r automatiche

Indirizzo di rientro in main

...k

automatiche

a2

a1 28

12

argomenti

void foo(...) {

...k = mcd(&a1,&a2) } ...

funzione chiamante

int mcd(int *a, int *b){

int r;

} ...

funzione chiamata

main {

(18)

Stringhe

In memoria le stringhe sono degli array di tipo char, con una particolarità in più, che le fa riconoscere da operatori e funzioni come stringhe e non come normali array:

l’elemento dell’array che segue l’ultimo carattere della stringa

deve contenere il carattere NULL o ‘\0’ (detto in questo caso

terminatore); si dice pertanto che una stringa é un “array di

tipo char null terminated“.

(19)

Inizializzazione di variabili stringa

Se nella dichiarazione-inizializzazione si omette la dimensione dell’array, questa viene automaticamente definita dalla lunghezza della costante stringa aumentata di uno, per far posto al terminatore (in questo caso la stringa non può più essere “allungata”!):

char Saluto[] = “Ciao”;

allocato in memoria array con 5 elementi

(20)

Dichiarazione di stringhe

Es.:

char MiaVar[30];

Dichiara la variabile MiaVar come array di tipo char con massimo 30 elementi. Affinché MiaVar sia identificata (in lettura) da operatori e funzioni come stringa, dobbiamo inserire nell’array una serie di caratteri terminati da un NULL.

Se vogliamo che MiaVar presenti a operatori e funzioni la stringa

“Ciao”, dobbiamo scrivere invece le istruzioni:

MiaVar[0]=’C’; MiaVar[1]=’i’;

MiaVar[2]=’a’; MiaVar[3]=’o’;

MiaVar[4]=’\0’;

impegnando così 5 elementi dell’array dei 30 disponibili (i

rimanenti 25 saranno ignorati).

(21)

Considerazioni

ATTENZIONE:

In caso che si creino delle stringhe con un numero di caratteri

(compreso il terminatore) maggiore di quello dichiarato, il

programma non produce direttamente messaggi di errore, ma

invade zone di memoria non di sua pertinenza, con

conseguenze imprevedibili (spesso si verifica un errore fatale

a livello di sistema operativo).

(22)

C libreria string.h

La libreria string (string.h) contiene funzioni di manipolazione di stringhe

Prototipo Descrizione

char *strcpy(char *s, char *cs); copia cs in s e ritorna s char *strcat(char *s, char *cs); concatena cs ad s e ritorna s

int strcmp(char *cs1, char *cs2); confronta cs1 e cs2; se cs1 < cs2 il valore di ritorno è < 0; se cs1 > cs2 il valore di ritorno è > 0;

se le due stringhe sono uguali il valore di ritorno è 0 char *strstr(char *cs1, char *cs2); restituisce un puntatore alla prima occorrenza in

cs1 della stringa cs2

size_t strlen(char *cs); restituisce la lunghezza di cs

...

(23)

Array di puntatori

I puntatori, come qualsiasi altra variabile, possono essere raggruppati in array e dichiarati come:

Es.: int* A[10] ;

dichiara un array di 10 puntatori a int

Come il nome di un array equivale a un puntatore, così un

array di puntatori equivale a un puntatore a puntatore (con in

più l’allocazione della memoria puntata, come nel caso di

array generico)

(24)

Array di Stringhe

Il caso più frequente di array di puntatori é quello dell’array di stringhe, che consente anche l’inizializzazione (atipicamente) delle stringhe che costituiscono l’array

Es.: char* colori[3] = {‘’Blu’’, ‘’Rosso’’, ‘’Verde’’} ;

Le stringhe possono essere di differente lunghezza; in

memoria sono allocate consecutivamente e, sono riservati

tanti bytes quant’è la rispettiva lunghezza (terminatore

compreso).

(25)

Array di puntatori

suit[4] indica un array di 4 elementi

char* suit[4] = {“Heart”, “Diamond”,

“Clubs”, “Spades”}

Ogni elemento dell’array è un puntatore ad un char, l’array contiene in realtà soltanto i puntatori al primo carattere di ogni stringa. Pur avendo l’array suit

dimensione fissa, si può accedere a stringhe di qualsiasi

lunghezza.

(26)

C libreria utilità stringhe

Problema: Data una stringa qualsiasi verificare se è palindroma

Una stringa è palindroma quando ha uguali i caratteri che hanno la stessa distanza dal centro della stringa. Per esempio

Palindromi NON palindromi

ANNA AMARA

ADA AROMA

DEOED ODE

baccdccab abcab

detta n la lunghezza della stringa, se è palindroma sarà:

s[i]=s[n-1-i] per ogni i=0,…,n-1

(27)

Esercizi su funzioni e array

Esercizi: usare le funzioni di utilità per vettori e per stringhe

1. Generato in modo random un vettore contenente N interi relativi compresi tra –M ed M mediante una procedura, risolvere i seguenti problemi :

scrivere un programma che stampi tutti i numeri positivi e la loro posizione scrivere un programma che stampi tutti i numeri minori o uguali a zero scrivere un programma che stampi il più grande ed il più piccolo e le loro

posizioni

scrivere un programma che stampi tutti i numeri maggiori di un valore dato e le posizioni

scrivere una procedura che restituisca tutte le posizioni dei numeri negativi 2. Definire una funzione Uguali2 che prenda in input un vettore V di interi di

lunghezza n, e restituisca:

true se il vettore contiene almeno due numeri uguali, false altrimenti Esempi: Se V=[1,22,13,24,5] allora Uguali2(V) à false

Se invece V=[1,2,6,24,2] è Uguali2(V) à true

(28)

Esercizi su funzioni e array

3. Definire una procedura PrecSegueX che abbia in input un vettore V di interi di lunghezza n, ed un numero X, e:

inserisca all’inizio di V i valori di V minori o uguali ad X (preservandone l’ordine);

inserisca in seguito tutti i valori di V maggiori di X (preservandone l’ordine).

Esempio: Sia V= [56,35,4,2,22]. L’output di PrecSegueX(V,40) deve essere: V=[35,4,2,22,56]

4. Definire una funzione ContaCifre che prenda in input un vettore V di interi di lunghezza n, ed un numero X e conti quante volte tutte le cifre di X siano contenute negli elementi che compongono il vettore

Esempio: Siano V=[484,325,12,8489,48,12487,1284] e X=48;

ContaCifre(V,7,48) à 4

(sono evidenziati i numeri che contengono al loro “interno” il numero 48).

5. Definire una procedura GoDestra, che, assegnato un vettore V di n elementi ed un intero m, 0£ m £ n, sposti verso destra di m passi tutti gli elementi del vettore V

Esempio: Sia V=[7,8,9,0] ed n=4 otteniamo GoDestra(V,3) fa diventare V=[8,9,0,7]

(29)

Esercizi su funzioni e array

6. Scrivere una procedura Comuni, che assegnati due vettori V1, V2 di

dimensioni rispettivamente n1 ed n2, ponga in un altro vettore V3 tutti e soli gli elementi di V1 che compaiono anche in V2, conservando l’ordine con cui compaiono in V1

Esempio: Siano V1=[1,2,3,4,5], V2=[5,0,3,0,1], V3 qualunque.

Eseguiamo Comuni(V1, V2,V3). Allora V3 diventa [1,3,5]

7. Definire una procedura PariDispari che dato un vettore V di interi di lunghezza n:

ponga all’inizio di V i valori di V pari, nello stesso ordine in cui si trovavano in V;

li faccia seguire dai valori di V dispari, di nuovo nello stesso ordine in cui si trovano in V.

Esempio: Sia V= [5,3,4,2,1]. Eseguiamo PariDispari si deve avere: V = [4,2,5,3,1]

8. Scrivere una funzione che dato un array V di interi di dimensione n

restituisce true se nell’array V c’è un valore che è uguale alla somma di tutti i valori che lo precedono, false altrimenti

Esempio. V=[1, 4, 4, 9, 3] la funzione restituisce true perché V[3]=9=1+4+4

V=[1,3,5,8,3] la funzione restituisce false

(30)

Esercizi su funzioni e array

9. Scrivere una procedura che dati 2 array di interi V1 e V2 di dimensione n restituisce nell’array V3 gli elementi che appartengono a V1 ma non a V2 non ripetuti e in N3 il numero di tali elementi

Esempio: V1= [2, 4, 4, 5, 3] e V2= [7, 3 ,10 ,6 ,7] si deve ottenere V3= [ 2, 4, 5] con N3 =3

10. Scrivere una funzione che data una stringa s ed un carattere car restituisce il numero massimo di caratteri car consecutivi presenti nell’array

Esempio: s = ‘abcaacaaabaa', car=’a’ la funzione deve restituire 3 11. Scrivere una procedura che dato un array a ordinato di dimensione N

inserisce nell’array il valore x in modo tale che l’array dopo l’inserimento sia ancora ordinato

Esempio: Siano a = [2, 3, 7, 11, 24] e x =5 si deve ottenere a = [2, 3, 5, 7, 11,24 ]

(31)

Esercizi su funzioni e array

12. Scrivere un programma che, dati due vettori di interi di dimensione N, ne costruisca un terzo di dimensione 2N i cui elementi di posizione pari siano gli elementi del primo vettore e gli elementi di posizione dispari siano gli

elementi del secondo vettore. Strutturare il programma in procedure e funzioni

13. Scrivere un programma che, dato un vettore V1 di reali di dimensione N, ne generi un altro V2 così definito: il primo elemento di V2 è dato dal prodotto degli elementi 1 e 2 di V1, il secondo elemento di V2 è dato dal prodotto degli elementi 3 e 4 di V1, e così via

(32)

Esercizi su funzioni e array

14.Scrivere una procedura che genera un vettore V di numeri reali di dimensioni N (N£100). Con tale procedura scrivere un programma che

stampi prima tutti gli elementi di posto dispari e poi quelli di posto pari,

letto un indice h stampi l’indice ed il valore del più piccolo fra i numeri maggiori di V[h];

stampi l’indice ed il valore dei numeri di valore dispari massimo e minimo;

si costruisca e quindi si stampi un secondo array di N elementi tali che il primo

elemento contenga la somma di tutti gli N numeri, il secondo la somma dei numeri dal secondo in poi, il terzo la somma dal terzo in poi e così via;

si stampi l’indice ed il valore dell’elemento massimo fra gli elementi di posto dispari, quindi l’indice ed il valore del minimo fra gli elementi di posto pari;

letto un indice h, si costruisca e quindi si stampi un array di N elementi tali che il

primo sia quello specificato dall’indice, il secondo sia quello precedente e così fino al primo, poi proseguendo dall’ultimo retrocedendo fino a completare l’array.

15.Scrivere un programma che prenda in input un vettore già ordinato di interi e stampi in output l’istogramma delle occorrenze di ogni elemento del vettore.

Esempio. dato il vettore V=[1,1,1,3,5,5,7,7,7,7,10,10], deve stampare:

1 ***

3 *5 **

7 ****

10 **

Riferimenti

Documenti correlati

Generalmente il confronto può essere fatto tra due generici puntatori che puntano allo stesso tipo di dato; questo confronto è comunque significativo solo nel caso in

● Se gli estremi degli scaglioni e/o le percentuali cambiano, devo cambiare solo l'array e non il programma che fa la ricerca!.. Algoritmi su

 Evitare l'uso di array paralleli trasformandoli in array Evitare l'uso di array paralleli trasformandoli in array di oggetti:.

Questo equivale a dire che occorre di- mostrare formalmente che il massimo ` e sempre il primo elemento della lista.. Mos- triamo una bozza di dimostrazione

ƒ restituisce un puntatore che contiene l’indirizzo del blocco di memoria allocato, cioè della variabile, la quale sarà quindi accessibile dereferenziando il puntatore. ƒ la

■ Quindi il vero argomento della prima funzione non é la seconda funzione, ma un normale valore, che può avere qualsiasi origine (variabile, espressione ecc...), e in particolare

Poiché la memoria heap è limitata,  questa può essere esaurita e quindi è 

¨  L’espressione a[i] restituisce il valore della variabile con indice i, quindi il tipo di questa espressione è il tipo base dell'array. Accesso agli elementi di