Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Informatica c++ basi di informatica, Sintesi del corso di Informatica

C++ basi programmazione, sintesi codici utili per la programmazione

Tipologia: Sintesi del corso

2020/2021

Caricato il 21/01/2021

marco-maina-2
marco-maina-2 🇮🇹

1 documento

1 / 5

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Puntatori e Funzioni
Funzioni che restituiscono puntatori
Il valore di ritorno restituito da una funzione può essere di qualsiasi tipo,
compreso il tipo puntatore.
Come in generale, il valore di ritorno, anche se é un puntatore, viene
trasmesso by value e quindi ne viene creata una copia nel programma
chiamante; ciò garantisce che il puntatore sopravviva alla funzione anche se
è stato creato all'interno del suo ambito.
Tuttavia la variabile puntata potrebbe non sopravvivere alla funzione (se é
stata creata nel suo ambito e non dichiarata static). Ciò porterebbe a un errore
di dangling references
. Notare l'analogia con il tipo di errore generato quando
un valore di ritorno, trasmesso by reference
, corrisponde a una variabile che
cessa di esistere: in quel caso tuttavia, il compilatore ha il controllo della
situazione e quindi può segnalare l'errore (o almeno un warning
); nel caso di un
puntatore, invece, il suo contenuto (cioè l'indirizzo della variabile puntata)é
determinato in esecuzione e quindi l'errore non può essere segnalato dal
compilatore. Spetta al programmatore fare la massima attenzione a che ciò non
si verifichi.
Il più frequente uso di funzioni che restituiscono puntatori si ha nel caso di
puntatori achar, cioè di stringhe. Nella stessa libreria Run-time ci sono molte
funzioni che restituiscono stringhe.
Esempio di funzione di libreria:
char* strcat(char* str1, char* str2);
concatena la stringa str2 alla stringa str1 e restituisce il risultato sia nella
stessa str1 che come valore di ritorno. Notare che in questo caso non c'è
pericolo di errore, purchè lo spazio di memoria per str1 sia stato
adeguatamente allocato nel programma chiamante.
[p33]
Es.:
int* funz();
dichiara una funzione funz che restituisce un valore
puntatore a int
pf3
pf4
pf5

Anteprima parziale del testo

Scarica Informatica c++ basi di informatica e più Sintesi del corso in PDF di Informatica solo su Docsity!

Puntatori e Funzioni

Funzioni che restituiscono puntatori

Il valore di ritorno restituito da una funzione può essere di qualsiasi tipo , compreso il tipo puntatore.

Come in generale, il valore di ritorno , anche se é un puntatore , viene trasmesso by value e quindi ne viene creata una copia nel programma chiamante ; ciò garantisce che il puntatore sopravviva alla funzione anche se è stato creato all'interno del suo ambito.

Tuttavia la variabile puntata potrebbe non sopravvivere alla funzione (se é stata creata nel suo ambito e non dichiarata static ). Ciò porterebbe a un errore di dangling references. Notare l'analogia con il tipo di errore generato quando un valore di ritorno , trasmesso by reference , corrisponde a una variabile che cessa di esistere: in quel caso tuttavia, il compilatore ha il controllo della situazione e quindi può segnalare l'errore (o almeno un warning ); nel caso di un puntatore , invece, il suo contenuto (cioè l' indirizzo della variabile puntata ) é determinato in esecuzione e quindi l'errore non può essere segnalato dal compilatore. Spetta al programmatore fare la massima attenzione a che ciò non si verifichi.

Il più frequente uso di funzioni che restituiscono puntatori si ha nel caso di puntatori a char , cioè di stringhe. Nella stessa libreria Run-time ci sono molte funzioni che restituiscono stringhe.

Esempio di funzione di libreria:

char strcat(char str1** , char str2);*

concatena la stringa str2 alla stringa str1 e restituisce il risultato sia nella stessa str1 che come valore di ritorno. Notare che in questo caso non c'è pericolo di errore, purchè lo spazio di memoria per str1 sia stato adeguatamente allocato nel programma chiamante.

[p33]

Es.: int funz(); dichiara* una funzione funz che restituisce un valore puntatore a int

Puntatori a Funzione

In C++ (come in C ) esistono anche i puntatori a funzione! Questi servono quando il programma deve scegliere quale funzione chiamare fra diverse possibili, e la scelta non é definita a priori ma dipende dai dati del programma stesso. Questo processo si chiama late binding ("aggancio ritardato"): gli indirizzi delle funzioni da chiamare non vengono risolti al momento della compilazione, come avviene normalmente ( early binding ) ma al momento

dell'esecuzione.

I puntatori a funzione non devono essere definiti , ma solo dichiarati , come nel seguente esempio:

int (pfunz)(double , char* );**

dichiara un puntatore a funzione pfunz che restituisce un puntatore a int e ha due argomenti : il primo é di tipo double , il secondo é un puntatore a char. Notare le parentesi intorno al nome della funzione , in assenza delle quali la dichiarazione sarebbe interpretata in modo diverso (una normale funzione pfunz che restituisce un puntatore a puntatore a int ).

Nel corso del programma il puntatore a funzione deve essere assegnato (o inizializzato ) con il nome di una funzione "vera", che deve essere precedentemente dichiarata con lo stesso tipo del valore di ritorno e gli stessi argomenti del puntatore. Continuando l'esempio precedente:

int funz1(double , char );**

int funz2(double , char );**

if ( ......... ) pfunz = funz1 ;

else pfunz = funz2;

notare che i nomi delle funzioni e del puntatore vanno indicati da soli, senza i loro argomenti (e senza le parentesi).

In una chiamata della funzione , tutti i testi di C dicono che il puntatore va dereferenziato (in realtà non é necessario):

(pfunz)(12.3,"Ciao");* ... ma va bene anche: pfunz(12.3,"Ciao");

Funzioni con argomenti puntatori a funzione

E' noto che, quando nella chiamata di una funzione compare come argomento un'altra funzione , questa viene eseguita per prima e il suo valore di ritorno é utilizzato come argomento dalla prima funzione. 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 in questo caso è il risultato dell'esecuzione di un'altra funzione (il cui tipo di valore di ritorno deve coincidere con il tipo dichiarato dell' argomento ).

Quando invece una funzione dichiara fra i suoi argomenti un puntatore a funzione , allora sono parametrizzate proprio le funzioni e non i loro valori di ritorno. Nelle chiamate é necessario specificare come argomento il nome di una funzione "vera", precedentemente dichiarata , che viene sostituito a quello del puntatore.

l'istruzione n=pfunz(r) viene sostituita la prima volta con n=funz1(r) e la seconda volta con n=funz2(r). Notare che, nelle chiamate , l' argomento - funzione deve essere a sua volta specificato senza argomenti e senza le parentesi tonde.

Nell'esempio abbiamo supposto che la variabile r , argomento della pfunz , sia creata all'interno della fsel ; anche se r fosse passato dal programma chiamante , la forma: fsel(funz1(r)) sarebbe comunque errata: l'unico modo per passare r potrebbe essere quello di dichiararlo come ulteriore argomento della fsel , cioè:

void fsel(float, int (pfunz)(float));* e nelle chiamate specificare:

Es.: dichiarazioni : void fsel(int ()(float)); int funz1(float); int funz2(float);*

chiamate : fsel(funz1); fsel(funz2);

definizione fsel : void fsel(int (pfunz)(float)) { .... n = pfunz(r); .....}* (dove n é di tipo int e r é di tipo float )

fsel(r, funz1); ...oppure... fsel(r, funz2);