La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

2000 Prentice Hall, Inc. All rights reserved. Attivazione di funzioni La chiamata/attivazione di funzione viene indicata citando il nome della funzione.

Presentazioni simili


Presentazione sul tema: "2000 Prentice Hall, Inc. All rights reserved. Attivazione di funzioni La chiamata/attivazione di funzione viene indicata citando il nome della funzione."— Transcript della presentazione:

1 2000 Prentice Hall, Inc. All rights reserved. Attivazione di funzioni La chiamata/attivazione di funzione viene indicata citando il nome della funzione e precisando i parametri attuali I parametri formali rappresentano un riferimento simbolico (identificatori) a oggetti utilizzati allinterno della funzione –il loro valore iniziale viene assegnato ad ogni chiamata della funzione usando i valori dei parametri attuali forniti dal programma chiamante –i parametri formali sono contenitori, quelli attuali sono i valori da copiarvi Nel corpo del main, o di unaltra funzione, la chiamata di funzione indica il punto e la modalità in cui va eseguita (attivata) la parte di codice presente nella sua definizione Lambiente locale di una funzione è costituito da: –parametri formali definiti nellintestazione della definizione –parte dichiarativa locale (variabili, costanti, ecc..)

2 2000 Prentice Hall, Inc. All rights reserved. Chiamata di sottoprogrammi (1) La chiamata di un sottoprogramma/funzione comporta: –allatto della chiamata, la cessione del controllo dellesecuzione dal chiamante al chiamato –lesecuzione del codice del chiamato, con un proprio ambiente di esecuzione –al termine dellesecuzione il ritorno del controllo al chiamante, allistruzione o operazione successiva a quella di chiamata Per la corretta gestione del controllo dell'esecuzione è indispensabile il salvataggio dellindirizzo di ritorno del chiamante In C lambiente locale di esecuzione di una funzione si crea al momento della chiamata e termina al termine dellesecuzione della funzione

3 2000 Prentice Hall, Inc. All rights reserved. Chiamata di sottoprogrammi (2)

4 2000 Prentice Hall, Inc. All rights reserved. Scambio delle informazioni Lo scambio di informazioni tra funzione chiamante e chiamata può avvenire mediante passaggio dei parametri –per fornire i valori in ingresso al chiamato, ma anche per mettere in grado il chiamato di fornire al chiamante i risultati di operazioni –alla chiamata il valore dei parametri attuali viene copiato nei corrispondenti parametri formali Oppure mediante il valore restituito da una funzione –per fornire un valore al chiamante –allesecuzione dellistruzione return il valore di espressione viene restituito al chiamante Oppure tramite luso di variabili globali, cioè visibili, referenziabili, modificabili da tutte le parti del programma e sottoprogrammi –Nei programmi di buona qualità laccesso e la modifica di variabili globali da parte dei sottoprogrammi è ridotto al minimo

5 2000 Prentice Hall, Inc. All rights reserved. Esecuzione e ambienti locali (1) int main() { … coeff = fattoriale(n) / (fattoriale(k) * fattoriale(n-k)); } int fattoriale (int a){ // calcolo del fattoriale: versione iterativa int i, fatt = 1; if( a!=0 ) for( i=1; i<=a; i=i+1 ) fatt = fatt * i; return fatt; }

6 2000 Prentice Hall, Inc. All rights reserved. Esecuzione e ambienti locali (2)

7 2000 Prentice Hall, Inc. All rights reserved. Ambienti di esecuzione in C (1) Lambiente di esecuzione di una funzione viene creato al momento della chiamata e rilasciato al suo termine In una sequenza di chiamate annidate lultimo chiamato è il primo a terminare main funzione1 funzione2 funzione1 main Per gestire l'annidamento è necessaria una gestione specifica degli indirizzi di ritorno, deve essere prevista una zona di memoria di lavoro separata per il salvataggio di ogni indirizzo di ritorno delle funzioni non ancora terminate

8 2000 Prentice Hall, Inc. All rights reserved. Ambienti di esecuzione in C (2) Il C prevede che esista un ambiente di esecuzione per ogni attivazione di funzione ed essendo lultima chiamata la prima a terminare in C la gestione degli indirizzi di ritorno è a pila LIFO (Last In First Out) La pila di gestione dellambiente di esecuzione di funzioni C è costituita da un insieme di record di attivazione –esiste un record per ogni sottoprogramma attivo e non ancora terminato –lultimo sottoprogramma attivato è il primo a terminare –l'indirizzo di ritorno in cima alla pila è sempre relativo all'ultimo sottoprogramma attivato (cioè il primo che deve terminare) –questa modalità di gestione degli ambienti di esecuzione consente anche di supportare la ricorsione Un record di attivazione è unarea di memoria contenente: –lambiente locale della funzione (variabili locali e parametri formali) –lindirizzo di ritorno al chiamante –Le informazioni per gestire la memoria nella modalità a stack (pila)

9 2000 Prentice Hall, Inc. All rights reserved. Record di attivazione Ad ogni attivazione di una funzione viene allocato in cima alla pila un record di attivazione con: –lindirizzo di ritorno al chiamante che viene scritto nellapposita locazione –i parametri formali che ricevono i valori iniziali da quelli dei parametri attuali della chiamata –le variabili locali che, al momento della chiamata, hanno un valore non significativo Al termine dellattivazione il record viene rilasciato, cioè tolto dalla pila (liberando la memoria) e quindi le variabili locali vengono perse La dimensione del record di attivazione di una funzione è nota e fissa e viene determinata in fase di compilazione Non è noto il numero di chiamate (di attivazioni) annidate dei sottoprogrammi: tale numero dipende dallesecuzione del programma

10 2000 Prentice Hall, Inc. All rights reserved. Gestione a pila della memoria (1) I record vengono allocati in memoria uno sopra laltro –la pila dei record cresce dal basso verso lalto –il primo record accessibile dello stack è relativo allultima funzione attivata e non ancora terminata –inizialmente il primo record di attivazione allocato è quello per il main() Esiste un registro della CPU chiamato Stack Pointer che contiene lindirizzo della cima della pila In ogni record di attivazione è memorizzato anche il valore di stack pointer relativo allelemento sottostante nella pila –cioè lindirizzo nella pila del record di attivazione della funzione chiamante contenente il suo stato prima della chiamata (da non confondere con lindirizzo di ritorno al chiamante che indica dove riprendere lesecuzione) Una parte di memoria RAM è dedicata a contenere larea di stack, che ha dimensioni prefissate in fase di compilazione –si parla di stack overflow quando questa capacità viene superata (troppi annidamenti di chiamate con record di attivazione troppo grossi)

11 2000 Prentice Hall, Inc. All rights reserved. Gestione a pila della memoria (2)

12 2000 Prentice Hall, Inc. All rights reserved. La soluzione ad un problema si dice ricorsiva (lalgoritmo è ricorsivo) se fa uso di se stessa ES: ordinare alfabeticamente un elenco di nomi. Soluzione con algoritmo in forma ricorsiva: Se lelenco è vuoto il procedimento è terminato Altrimenti Cercare primo elemento nellinsieme dato Spostare lelemento in prima posizione Ordinare alfabeticamente linsieme rimanente Fine procedimento La soluzione ad un problema (lalgoritmo) può ammettere o non ammettere formulazione ricorsiva Tutti i problemi che ammettono soluzioni ricorsive ammettono anche soluzioni di tipo iterativo Ricorsione (1/9)

13 2000 Prentice Hall, Inc. All rights reserved. Funzioni ricorsive –Sono funzioni che richiamano se stesse al loro interno (nella definizione) –La funzione di per sé è in grado solo di risolvere un caso base, ovvero un problema molto semplice –Il problema complesso viene comunque risolto perché viene suddiviso in: Cosa la funzione può risolvere/fare Cosa la funzione non può fare, parte che assomiglia molto al problema originale Per risolvere la seconda parte, la funzione lancia una copia di se stessa sul sottoproblema (passo ricorsivo) La divisione è reiterata finchè il sottoproblema del passo ricorsivo non lavora sul caso base che invece è immediatamente risolvibile Quando finalmente il caso base viene risolto –Il risultato del caso base viene ritornato alla chiamata dellultimo passo ricorsivo e cosi via a ritroso i risultati ottenuti per i sottoproblemi vengono passati alle varie chiamate ricorsive della funzione –Ogni chiamata ricorsiva lavora via via su un problema più piccolo fino a risolvere lintero problema (N istanze di attivazione della funzione) Ricorsione (2/9)

14 2000 Prentice Hall, Inc. All rights reserved. Esempio: il fattoriale 5! = 5 * 4 * 3 * 2 *1 Tenendo conto che 5! = 5 * 4! 4! = 4 * 3! –E evidente che il problema del fattoriale può essere risolto con un algoritmo di ricorsione Come funziona? –Si risolve il caso base: 1! = 0! = 1 –Si inserisce questo risultato a ritroso nei calcoli ricorsivi più complessi 2! = 2 * 1! = 2 * 1 = 2 3! = 3 * 2! = 3 * 2 = 6 Ricorsione (3/9)

15 2000 Prentice Hall, Inc. All rights reserved. Esempio: la serie di Fibonacci 0, 1, 1, 2, 3, 5, 8, 13, 21, … –La regola è che ogni numero della serie è la somma dei 2 precedenti Come funziona? –Fib(n) = Fib(n-1) + Fib(n-2) che è una formula ricorsiva, dove n è lindice del numero nella serie partendo dal primo numero che ha indice zero –Fib(0) = 0, Fib(1) = 1 che è la soluzione del caso base int fibonacci(int n){ if (n==0 || n==1) //caso base return n; else return fibonacci(n-1) + fibonacci(n-2); } Ricorsione (4/9)

16 2000 Prentice Hall, Inc. All rights reserved. Ricorsione (5/9) f( 3 ) f( 1 ) f( 2 ) f( 1 )f( 0 )return 1 return 0 return + +

17 2000 Prentice Hall, Inc. All rights reserved. Ricorsione (6/9) 1/* Fig. 4.12: fig04_12.c – Funzione ricorsiva di Fibonacci */ 2#include 3long fibonacci(long); 4 5int main() 6 long result, number; 7 8 printf(Inserisci un intero: "); 9 scanf("%ld", &number); 10 result = fibonacci(number); 11 printf("Fibonacci(%ld) = %ld\n", number, result); 12 return 0: 13} 14 15long fibonacci(long n){ /* Definizione della funzione ricorsiva */ 16 if (n == 0 || n == 1) return n; 17 else return fibonacci(n - 1) + fibonacci(n - 2); 18} 1. Prototipo della funzione 2. Chiamata della funzione 3. Definizione della funzione ricorsiva Esecuzione del programma Inserisci un intero: 10 Fibonacci(10) = 55

18 2000 Prentice Hall, Inc. All rights reserved. Esempio: Procedura ricorsiva per visualizzare la rappresentazione binaria pesata di un numero intero positivo –riceve un intero positivo da convertire in binario –ne restituisce la rispettiva sequenza di 0 e 1 della forma binaria void Converti_bin (int num) { int resto; // variabile dellambiente locale resto = num%2; if (num >= 2) // costrutto condizionale Converti_bin (num/2); // chiamata ricorsiva else { } // ramo senza chiamata ricorsiva (si può omettere) printf("%d", resto); } Ricorsione (7/9)

19 2000 Prentice Hall, Inc. All rights reserved. Ricorsione (8/9)

20 2000 Prentice Hall, Inc. All rights reserved. Ricorsione (9/9)


Scaricare ppt "2000 Prentice Hall, Inc. All rights reserved. Attivazione di funzioni La chiamata/attivazione di funzione viene indicata citando il nome della funzione."

Presentazioni simili


Annunci Google