introduzione al c unità 5 funzionisalza/fi-c/5-c-17-18.pdfmodalità, da tutti i moderni linguaggi...
TRANSCRIPT
Corso di Fondamenti di Informatica
Ingegneria delle Comunicazioni – BCOR
Ingegneria Elettronica – BELR
Introduzione al C
Unità 5 – Funzioni
S. Salza, C. Ciccotelli, D. Bloisi, S. Peluso, A. Pennisi
2017/2018
Sommario – Unità 5
• Definizione di funzioni
• Passaggio dei parametri
• Esecuzione di una funzione
• Variabili dichiarate in una funzione e visibilità
• Gestione della memoria su chiamate di funzioni
Unità 5 - Funzioni Pagina 2
2017/2018
Astrazione delle operazioni
• Astrazione sulle operazioni: concentrarsi su cosaun'operazione deve fare e non su come lo fa
• È un paradigma fondamentale per decomporre la complessità degli algoritmi e dei programmi:
- ad alto livello si assume l'esistenza di moduli di programma che realizzano determinate operazioni
- successivamente questi moduli vengono sviluppati separatamente e individualmente
• L'astrazione sulle operazioni è supportata, con diverse modalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.)
Unità 5 - Funzioni Pagina 3
2017/2018
Funzioni
• In C l'astrazione sulle operazioni si realizza attraverso la nozione di funzione
• Una funzione può essere vista come una scatola nera che svolge una determinata operazione
• La funzione viene chiamata da un altro modulo di programma (il main o un'altra funzione) per svolgere una specifica operazione
• Essa, oltre a compiere una serie di azioni, comunica con l'ambiente chiamante:
• ricevendo in ingresso una serie di parametri
• restituendo quando termina uno o più risultati
Unità 5 - Funzioni Pagina 4
2017/2018
Definizione di funzioni in C
tipoRisultato nomeFunzione(parametriFormali){
istruzioni
}
Intestazione
Corpo
• tipoRisultato: tipo del risultato restituito dalla funzione (e.g. int, double) oppure void se la funzione non restituisce risultato
• nomeFunzione: nome della funzione.
• parametriFormali: lista (eventualmente vuota) di dichiarazioni di
parametri (coppie tipo e nome) separate da virgola.
• istruzioni: corpo della funzione contenente le istruzioni da
eseguire all’invocazione della funzione stessa.
Unità 5 - Funzioni Pagina 5
2017/2018
Funzione main (sintassi alternative)
int main(){
...
}
int main(void){
...
}
void main(){
...
}
void main(void){
...
}
oppure
N.B. la lista dei parametri formali vuota può essere denotata con void
Unità 5 - Funzioni Pagina 6
2017/2018
Esempio: stampa potenza
void stampaPotenza(double b, double esp){
double r = pow(b,esp);
printf(“%f\n”, r);
}
• Questa funzione non restituisce risultato (tipo void)
• Essa chiama a sua volta la funzione di libreria pow, per
cui bisogna includere l'header della libreria math.h :
#include <math.h>
• Per invocarla bisogna inserire nel programma la relativa
chiamata, ad es.:
stampaPotenza(2, 32)
Unità 5 - Funzioni Pagina 7
2017/2018
Istruzione return
SINTASSI
returnespressione;
dove espressione è un’espressione il cui valore deve
essere compatibile con il tipo del risultato dichiarato
nell’intestazione della funzione
SEMANTICA
L’istruzione return eseguita all’interno di una funzione f
termina l’esecuzione della stessa e restituisce il risultato
nel punto del programma dove è stata invocata f
Unità 5 - Funzioni Pagina 8
2017/2018
Esempio: return nella funzione main
int main(){
...
return 0; // 0 indica la terminazione normale
}
• L'esecuzione dell'istruzione return fa sempreterminare la funzione, anche se ci sono altre istruzioni che seguono.
• Se il tipo del risultato di una funzione è void, allora l’istruzione return si può omettere, a meno che non si desideri interrompere l'esecuzione, la sintassi dell’istruzione è in questo caso:
return;
Unità 5 - Funzioni Pagina 9
2017/2018
Mancato return
#include <stdio.h>
#include <math.h>
double radice(double x) {
double r = sqrt(x);
return r;
}
int main(){
printf("%f\n", radice(4.0));
return 0;
}
Provare ad omettere l'una e/o l'altra istruzione di return e
controllare se e quando il compilatore gcc segnala l'errore
Unità 5 - Funzioni Pagina 10
2017/2018
Esempi di defininizione di funzioni
ESEMPIO 1
void stampaSaluto() {
printf("\nBuon giorno!\n");
}
ESEMPIO 2
double dist(double x1, double y1, double x2, double y2) {
// Calcola la distanza tra due punti
return sqrt(pow(x2-x1, 2) + pow(y2-y1, 2)) ;
}
Unità 5 - Funzioni Pagina 11
2017/2018
Esempio: potenza con doppio ciclo
#include <stdio.h>
int main() {
int base, esp, ris = 1;
printf("base = "); scanf("%d",&base);
printf("esp = "); scanf("%d", &esp);
while (esp > 0) {
esp--;
int m_ando = ris, m_tore = base, prod = 0;
while (m_tore > 0) {
m_tore--;
prod = prod + m_ando;
}
ris = prod;
}
printf("risultato = %d\n", ris);
return 0;
}
Unità 5 - Funzioni Pagina 12
2017/2018
Scomposizione in funzioni 1/2
int prodotto(int moltiplicando, int moltiplicatore) {
int risultato = 0;
while (moltiplicatore > 0) {
risultato = risultato + moltiplicando;
moltiplicatore--;
}
return risultato;
}
• Si può aumentare di molto la leggibilità del programma scomponendolo in funzioni
• Nella fattispecie, definiamo una funzione per il prodotto e
poi richiamiamola nel programma principale
Unità 5 - Funzioni Pagina 13
2017/2018
Scomposizione in funzioni 2/2
#include <stdio.h>
int prodotto(int, int); // Prototipo della funzione
int main() {
// Calcola la potenza usando la funzione prodotto
int base, esp, ris = 1;
printf("base = "); scanf("%d",&base);
printf("esp = "); scanf("%d", &esp);
int o_esp = esp; // ricorda il valore di esp
while (esp > 0) {
esp--;
ris = prodotto(ris, base);
}
printf("\n %d elevato a %d = %d", base, o_esp, ris);
return 0;
}Unità 5 - Funzioni Pagina 14
2017/2018
Passaggio dei parametri 1/2
• La definizione di una funzione presenta nell’intestazione
una lista di parametri formali. Questi parametri sono
utilizzati come variabili all’interno del corpo della funzione
• L’invocazione di una funzione contiene i parametri da
utilizzare come argomenti della funzione stessa. Questi
parametri sono detti parametri attuali, per distinguerli dai
parametri formali presenti nell’intestazione della
definizione della funzione
• Quando, attraverso una invocazione, attiviamo una
funzione, i parametri attuali sono legati ai parametri
formali. Esistono diversi modi possibili di effettuare
questo legame
Unità 5 - Funzioni Pagina 15
2017/2018
Chiamata per valore e per riferimento
Esistono due modi diversi per il passaggio dei parametri:
• PASSAGGIO PER VALORE
All'atto della chiamata viene preparata una copia dei valori dei
parametri attuali: su questa copia opera la funzione, mentre il valore
dei parametri attuali non viene modificato
• PASSAGGIO PER RIFERIMENTO
Alla funzione viene passato il riferimento alle variabili che
costituiscono i parametri attuali: la funzione opera direttamente su di
esse e quindi può modificarne il valore
Il C prevede esplicitamente solo il passaggio per valore
Unità 5 - Funzioni Pagina 16
2017/2018
Passaggio dei parametri per valore 1/2
• Sia pa un parametro attuale presente nell’invocazione della funzione e pf il corrispondente parametro formale nelladefinizione della funzione
• All'atto della chiamata per valore:
1. Viene valutato il parametro attuale pa (che è in generale un'espressione)
2. Viene associata al parametro formale pf una locazione di memoria
3. Tale locazione viene inizializzata al valore di pa
La funzione durante la sua esecuzione opera sui parametri
formali, cioè sulle locazioni a loro associate durante la
chiamata, lascia quindi intatto il valore dei parametri attuali
Unità 5 - Funzioni Pagina 17
2017/2018
Passaggio dei parametri per valore 2/2
• Il parametro formale pf si comporta esattamente come una variabile dichiarata all'interno della funzione e creata al momento di ciascuna chiamata della funzione
• La memoria rimane allocata al parametro formale solo durante l'esecuzione della funzione
• Al termine dell'esecuzione della funzione tali spazi di memoria vengono deallocati e i valori dei parametri formali non sono più accessibili
N.B. I valori delle variabili che compaiono nelle espressioni
che costituiscono i parametri attuali, non vengono alterati
durante l'esecuzione
Unità 5 - Funzioni Pagina 18
2017/2018
Esempio: passaggio per valore 1/5
#include <stdio.h>
int raddoppia(int); // Prototipo della funzione
int main() {
int a, b;
a = 5;
b = raddoppia(a + 1);
printf("\n a = %d b = %d\n", a, b);
return 0;
}
int raddoppia(int x) {
// Restituisce il doppio del valore passato
x = x * 2;
return x;
}
PARAMETRO ATTUALE
PARAMETRO FORMALE
Unità 5 - Funzioni Pagina 19
2017/2018
Esempio: passaggio per valore 2/5
1. Sono definite due variabili intere a, b e a è inizializzata
al valore 5.
2. Sono valutati i parametri attuali: nel nostro caso il parametro attuale è l’espressione a + 1 che ha
come valore 6.
3. E’ individuata la funzione da eseguire, cercando la
definizione di una funzione il cui prototipo sia conforme
alla invocazione: il nome della funzione deve essere lo
stesso e i parametri attuali devono corrispondere in
numero e tipo ai parametri formali (nel nostro caso la
funzione che cerchiamo deve avere la segnaturaraddoppia(int)).
Unità 5 - Funzioni Pagina 20
2017/2018
Esempio: passaggio per valore 3/5
4. L’esecuzione dell’unità di programma chiamante (nell’ esempio la funzione main) è sospesa
5. Sono riservate (allocate) in memoria locazioni per i parametri formali (considerati come variabili) e le altre eventuali variabili definite nella funzione: nell'esempio sarà riservata memoria per il parametro formale x
6. I valori dei parametri attuali sono associati ai corrispondenti parametri formali: nell’esempio il parametro formale x è inizializzato con il valore 6
Unità 5 - Funzioni Pagina 21
2017/2018
Esempio: passaggio per valore 4/5
7. Sono eseguite le istruzioni del corpo della funzione invocata (a partire dalla prima): nell’esempio il valore di x è moltiplicato per 2 e diventa 12
8. L’esecuzione della funzione invocata termina (o perl’esecuzione dell’istruzione return o perché non ci
sono altre istruzioni da eseguire): nell’esempiosi esegue l’istruzione return x
9. La memoria utilizzata per i parametri formali e le variabili della funzione è deallocata, perdendo qualsiasi informazione ivi contenuta: nell’esempio viene eliminata la locazione di memoria corrispondente al parametro formale x
Unità 5 - Funzioni Pagina 22
2017/2018
Esempio: passaggio per valore 5/5
10. Se la funzione restituisce un risultato, tale risultato diviene il valore dell’espressione costituita dall’invocazione nell’unità di programma chiamante: nell’esempio il risultato è 12
11. Si riprende l’esecuzione dell’unità di programma chiamante dal punto in cui era stata interrotta dall’invocazione: il valore 12 è assegnato alla variabile b
Nel passaggio di parametri per valore il contenuto delle
variabili usate come parametri attuali non viene mai
modificato. Il programma illustrato stampa quindi:
a = 5, b = 12
Unità 5 - Funzioni Pagina 23
2017/2018
Perché il C adotta il passaggio per valore?
• È un metodo sicuro: le variabili del chiamante e del chiamato sono completamente disaccoppiate
• Consente di ragionare per componenti e servizi: la struttura interna dei singoli componenti è irrilevante
• La funzione può anche modificare il contenuto dei parametri formali, senza alcun impatto sui valori dei parametri attuali nell’ambiente del chiamante
• La funzione chiamata e l'ambiente chiamante sono così del tutto disaccoppiati e non ci sono side effects
• Gli effetti della chiamata sono solo espliciti e ben visibili: valore restituito e azioni dirette della funzione
Unità 5 - Funzioni Pagina 24
2017/2018
Limiti del passaggio per valore
• Il passaggio per valore ha una semantica per copia
• La comunicazione tra ambiente chiamante e chiamato è limitata e unidirezionale, salvo che per il valore di ritorno (che però è uno solo)
• Impedisce a priori di scrivere funzioni che abbiano come scopo quello di modificare i dati passati dall’ambiente chiamante
• Impedisce di restituire all’ambiente chiamante più di un risultato
• Ad esempio non è possibile creare una funzione che restituisca quoziente e resto di una divisione
Unità 5 - Funzioni Pagina 25
2017/2018
Effetti del passaggio per valore
#include <stdio.h>
void swapVal(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
int main() {
int x = 12, y = 27;
printf("\nx = %d, y = %d\n", x, y);
swapVal(x, y);
printf("\nx = %d, y = %d\n", x, y);
return 0;
}
• Cosa fa la funzione swapVal?
• Cosa stampa il programma?
Unità 5 - Funzioni Pagina 26
2017/2018
Passaggio per riferimento
• Per avere una funzione swapVal che scambi realmente
scambio i valori delle variabili passate come parametri attuali ci vorrebbe un passaggio per riferimento
• Il passaggio per valore è un meccanismo troppo povero per consentire azioni questo tipo
• Occorre un metodo per consentire alla funzione di poter manipolare le variabili dell’ambiente delchiamante
In effetti diversi linguaggi di programmazione prevedono la
possibilità di passare i parametri per riferimento
Unità 5 - Funzioni Pagina 27
2017/2018
Passaggio per riferimento: principi
• Una funzione deve poter dichiarare, nella sua intestazione, che un parametro costituisce un riferimento
• In tal caso:
– il parametro formale indicato come riferimento non è più una variabile locale inizializzata al valore del parametro attuale, ma è un riferimento alla variabile originale (parametro attuale) nell’ambiente della funzione chiamante;
– ogni modifica fatta al parametro formale, in realtà viene effettuata sul parametro attuale della funzione chiamante (le modifiche fatte dall’ambiente chiamato si propagano all’ambiente chiamante)
Unità 5 - Funzioni Pagina 28
2017/2018
Passaggio per riferimento in C
• Il passaggio per riferimento è disponibile in molti
linguaggi di alto livello (Pascal, C++), ma non in tutti
• In particolare, NON è disponibile in C (almeno in modo
esplicito)
• Può però essere simulato tramite l’uso di puntatori, che
saranno discussi nella Unità 6
• Come si vedrà, un puntatore ha come valore l'indirizzo
di una variabile
• Passando per valore un puntatore, si passa un realtà il
riferimento a una variabile
Unità 5 - Funzioni Pagina 29
2017/2018
Variabili locali
• Il corpo di una funzione può contenere dichiarazioni di variabili
• Tali variabili vengono dette variabili locali
• Occorre precisare il significato di tali variabili locali, tramite due aspetti fondamentali:
- campo d’azione (nozione statica, che dipende dal testo del programma): cioè dove la variabile è visibile
- tempo di vita (è una nozione dinamica, che dipende dall’esecuzione del programma): cioè quando la variabile è disponibile, cioè le è allocata memoria
Unità 5 - Funzioni Pagina 30
2017/2018
Campo d’azione delle variabili locali
• Il campo d'azione (o scope) di una variabile è l'insieme
delle unità di programma in cui la variabile è visibile (cioè
accessibile e utilizzabile)
• Il campo di azione di una variabile locale è il corpo
della funzione in cui essa è dichiarata
• Più precisamente, una variabile dichiarata in un qualsiasi blocco (struttura{...}) è visibile in quel blocco (inclusi
eventuali blocchi interni), ma non è visibile all'esterno del blocco stesso.
• Una variabile non può essere utilizzata (nel corpo della
funzione) prima di essere dichiarata.
Unità 5 - Funzioni Pagina 31
2017/2018
Esempio
#include <stdio.h>
int raddoppia(int x) {
return x * 2;
}
void stampa() {
printf("%d\n", a); // ERRORE a non è definita
}
int main() {
int a = 5;
a = raddoppia(a);
stampa();
printf("\na = %d\n", a);
return 0;
}
Nella funzione stampa la variabile
a non è visibile, perché definita
nella funzione main
Unità 5 - Funzioni Pagina 32
2017/2018
Variabiliglobali
• È possibile in C definire variabili globali, cioè definite al
di fuori di una definizione di funzione
• Le variabili globali sono visibili in tutte le funzioni
• In ogni funzione sono visibili le variabili dichiarate
localmente e le variabili globali
• Nel fare questo, è buona norma mettere le definizioni di
queste variabili all'inizio del programma
• L'uso di variabili locali va limitato ed evidenziato visto
che esse costituiscono un canale di comunicazione
(non necessariamente evidente) tra tutte le funzioni
Unità 5 - Funzioni Pagina 33
2017/2018
Esempio
#include <stdio.h>
int a = 1; // Dichiarazione di variabile globale a
void f1() {
printf("In f1 a = %d\n", a);
// printf("b = %d", b); questa dava errore!!
}
int main() {
int b = 5;
f1();
a = b;
printf("In main a = %d\n", a);
return 0;
}
Unità 5 - Funzioni Pagina 34
2017/2018
Tempo di vita delle variabili
• Il tempo di vita di una variabile è il tempo in cui la variabile
rimane effettivamente accessibile in memoria durante
l'esecuzione.
• Le variabili locali a una funzione vengono create al
momento dell'attivazione della funzione (come i parametri
formali) e vengono distrutte al momento dell'uscita
dall'attivazione
• Le variabili globali restano in vita per tutta la durata
dell'esecuzione del programma.
• Il tempo di vita di una variabile è un concetto rilevante a
tempo di esecuzione. Da esso dipende l’insieme delle
variabili utilizzabili in ciascun punto del programma
Unità 5 - Funzioni Pagina 35
2017/2018
Esempio: tempo di vita delle variabili 1/2
#include <stdio.h>
int raddoppia(int x) {
int temp = x * 2;
return temp;
}
void stampa(int b) {
printf("Valeva: %d\n", b);
}
int main() {
int a = 5;
a = raddoppia(a);
a = raddoppia(a);
stampa(a);
printf("\n a = %d\n", a);
return 0;
}
Unità 5 - Funzioni Pagina 36
2017/2018
Esempio: tempo di vita delle variabili 2/2
• La variabile a inizia ad essere in vita quando viene
eseguita la sua dichiarazione nella funzione main.
• Il parametro x della funzione raddoppia (che corrisponde
ad una variabile locale) e la variabile locale temp iniziano
ad essere in vita quando viene invocata la funzione raddoppia e muoiono, al termine della sua esecuzione
• Ad ogni esecuzione di raddoppia corrispondono in
esecuzione, diverse istanze di variabili
• Analogamente il parametro x della funzione stampa nasce
e muore con l’esecuzione di stampa
Unità 5 - Funzioni Pagina 37
2017/2018
Esercizi
ESERCIZIO 5.1
Scrivere una funzione che calcoli il volume di una sfera,
dato il raggio. Scrivere un programma di prova che usi tale
funzione, leggendo da tastiera il valore del raggio e
stampando il volume della sfera con tale raggio
ESERCIZIO 5.2
Scrivere una funzione che dati due valori reali a e b
restituisca il massimo tra i due. Scrivere un programma di
prova per tale funzione, leggendo l’input da tastiera
Unità 5 - Funzioni Pagina 38
2017/2018
Layout di memoria
A tempo di esecuzione, il sistema operativo gestisce diverse
zone di memoria:
• TESTO: contiene il codice eseguibile del programma ed è
determinata e allocata a tempo di caricamento del codice
• DATI: contiene le variabili globali ed è determinata e allocata a
tempo di caricamento del codice
• HEAP: allocata e deallocata dinamicamente durante l’esecuzione
• STACK: (o pila dei record di attivazione), varia dinamicamente
durante l'esecuzione
Lo stack è gestito con un meccanismo a pila (catasta): è sempre
l'ultima porzione allocata ad essere deallocata per prima
Unità 5 - Funzioni Pagina 39
2017/2018
Pila dei record di attivazione
• Una pila (o stack) è una struttura dati con accesso LIFO
• Last In First Out : l’ultimo entrato è il primo a uscire
(Esempio: pila di piatti)
• A run-time il sistema operativo gestisce la pila dei record
di attivazione (RDA):
- per ogni attivazione di funzione viene creato un
nuovo RDA in cima alla pila
- al termine dell’attivazione della funzione il RDA viene
rimosso dalla pila
Unità 5 - Funzioni Pagina 40
2017/2018
Record di attivazione
• Un RDA (Record Di Attivazione) detto anche stack frame
è una porzione di memoria che allocata in cima allo stack
quando una funzione va in esecuzione
• Un RDA contiene tutto quanto è necessario tenere in
memoria per gestire della chiamata di una funzione:
‐ le locazioni di memoria per i parametri formali
‐ le locazioni di memoria per le variabili locali
‐ il valore di ritorno della funzione
‐ l'indirizzo di ritorno (nella funzione chiamante)
• Quando l'esecuzione della funzione termina, il suo RDA
viene deallocato (perché non serve più!)
Unità 5 - Funzioni Pagina 41
2017/2018
Organizzazione delo stack
INDIRIZZO DI RIENTRO
VALORE DI RIENTRO
VARIABILI LOCALI
PARAMETRI FORMALI
CIMA DELLO STACK
RDA della funzione gamma
RDA della funzione beta
RDA della funzione alfa
• L'ordine delle chiamate
è stato:alfa chiama beta
beta chiama gamma
• La prima a terminare sarà gamma e il suo
RDA sarà deallocato
• Riprende l'esecuzione di beta il cui RDA si
troverà allora in cima
allo stack
• . . .
INDIRIZZO DI RIENTRO
VALORE DI RIENTRO
VARIABILI LOCALI
PARAMETRI FORMALI
INDIRIZZO DI RIENTRO
VALORE DI RIENTRO
VARIABILI LOCALI
PARAMETRI FORMALI
Unità 5 - Funzioni Pagina 42
2017/2018
Esempio (codice del programma) 1/2
int B(int pb) {
/* b0 */ printf("In B. Parametro pb = %d\n", pb);
/* b1 */ return pb+1;
}
int A(int pa) {
Parametro/* a0 */ printf("In A.
/* a1 */ printf("Chiamata di B(%d).\n",
pa = %d\n", pa);
pa * 2 );
/* a2 */ int va = B(pa * 2);
/* a3 */ printf("Di nuovo in A. va = %d\n", va);
/* a4 */ return va + pa;
}
Unità 5 - Funzioni Pagina 43
2017/2018
Esempio (codice del programma) 2/2
int main() {
vm);
%d\n", vm);
/* m0 */ printf("In main.\n");
/* m1 */ int vm = 22;
/* m2 */ printf("Chiamata di A(%d).\n",
/* m3 */ vm = A(vm);
/* m4 */ printf("Di nuovo in main. vm =
/* m5 */ return 0;
}
Unità 5 - Funzioni Pagina 44
2017/2018
Output prodotto dal programma
In main.
Chiamata di A(22).
In A. Parametro pa
Chiamata di B(44).
= 22
In B. Parametro pb = 44
Di nuovo in A. va = 45
Di nuovo in main. vm = 67
Unità 5 - Funzioni Pagina 45
2017/2018
Program Counter (PC)
• Per comprendere cosa avviene durante l’esecuzione
del codice, è necessario fare riferimento, oltre che
alla pila dei RDA, al registro program counter (PC)
• A ciascun istante, il PC contiene l’indirizzo della
prossima istruzione da eseguire
Assumiamo che gli indirizzi delle istruzioni siano:
m0 abbia indirizzo 100
a0 abbia indirizzo 200
b0 abbia indirizzo 300
Unità 5 - Funzioni Pagina 46
2017/2018
Evoluzione della pila dei RDA
Figura 5.1
Unità 5 - Funzioni Pagina 47
2017/2018
Evoluzione della pila: chiamata di A
Prima dell’attivazione di A(vm), la pila dei RDA è come
mostrato in 1 nella Fig. 5.1:
1. Sono valutati i parametri attuali: in questo caso il
parametro attuale è l’espressione vm che ha come valore
l’intero 22
2. Sono determinate le caratteristiche della funzione chiamata:
parametri, varore di ritorno, variabili globali, sulla base della sua
definizione
3. E’ sospesa l’esecuzione della funzione chiamante (nell’esempio
la funzione main)
Unità 5 - Funzioni Pagina 48
2017/2018
Evoluzione della pila: creazione del RDA
4. È creato il RDA relativo all’attivazione correntedella funzione
chiamata: nell’esempio è creato il RDA relativo all’attivazione
corrente di A; il RDA contiene:
• le locazioni di memoria per i parametri formali
(nell’esempio, il parametro pa di tipo int);
• le locazioni di memoria per le variabili locali
(nell’esempio, la variabile va di tipo int);
• una locazione di memoria per il valore di ritorno (VR)
• una locazione di memoria per l’indirizzo di ritorno (IR)
5. Il valore dei parametri attuali è assegnato ai parametri formali:
nel nostro caso, il parametro formale pa è inizializzato con il
valore 22
Unità 5 - Funzioni Pagina 49
2017/2018
Evoluzione della pila: modifica del valore di PC
6. L’indirizzo di ritorno nel RDA è messo all’indirizzo della prossima
istruzione che deve essere eseguita nella funzione chiamante al
termine dell’invocazione: nel’esempio, l’indirizzo di ritorno
nel RDA relativo all’attivazione di A è impostato al valore 104,
che è l’indirizzo dell’istruzione di main corrispondente
all’istruzione m4, da eseguire quando l’attivazione di Asarà
terminata; a questo punto, la pila dei RDA è come mostrato in 2
nella Fig. 5.1;
7. Al program counter è assegnato l’indirizzo della prima istruzione
della funzione invocata: nell’esempio al program counter è
assegnato l’indirizzo 200, che è l’indirizzo della prima istruzione
di A;
Unità 5 - Funzioni Pagina 50
2017/2018
Evoluzione della pila: esecuzione di A
8. Si passa ad eseguire la prossima istruzione indicata dal PC, che
sarà la prima istruzione della funzione invocata: nell’esempio
l’istruzione di indirizzo 200, ovvero la prima istruzione di A
9. Dopo questi passi, le istruzioni della funzione chiamata A sono
eseguite in sequenza. In particolare, avverrà l’attivazione,
l’esecuzione e la terminazione di eventuali funzioni a loro volta
invocate nella funzione chiamata
10. Nell’esempio, avverrà l’attivazione, l’esecuzione e la terminazione
della funzione B, con un meccanismo analogo a quello adottato
per A; la pila dei RDA passerà attraverso gli stati 3 e 4
Unità 5 - Funzioni Pagina 51
2017/2018
Evoluzione della pila: terminazione di A
Analizziamo ora in dettaglio cosa avviene al momento della
terminazione dell’attivazione di A, cioè quando viene eseguita
l’istruzione return va+pa;
Prima dell’esecuzione, la pila dei RDA è come mostrato in 4 nella
Fig. 5.1 (in realtà, la zona di memoria predisposta a contenere il
valore di ritorno, indicata con VR nella figura, è inizializzata
contestualmente all’esecuzione dell’istruzione return, e non
prima).
Unità 5 - Funzioni Pagina 52
2017/2018
Evoluzione della pila: valore di ritorno di A
11. Al PC è assegnato il valore memorizzato nella locazione di
memoria riservata all’indirizzo di ritorno nel RDA corrente:
nell’esempio tale valore è pari a 104, che è proprio l’indirizzo,
memorizzato in IR, della prossima istruzione di main che dovrà
essere eseguita;
12. Nel caso la funzione invocata preveda la restituzione di un valore
di ritorno, tale valore è memorizzato in un’apposita locazione di
memoria del RDA corrente: nell’esempio, il valore 67, risultato
della valutazione dell’espressione va+pa è assegnato alla
locazione di memoria indicata con VR, predisposta per contenere
il valore di ritorno;
Unità 5 - Funzioni Pagina 53
2017/2018
Evoluzione della pila: rientro al chiamante
13. Il RDA relativo all’attivazione corrente è eliminato dallo stack;
contestualmente all’eliminazione del RDA dalla pila dei RDA, un
eventuale valore di ritorno è copiato in una locazione di
memoria del RDA del chiamante:
• Nell’esempio il RDA relativo all’attivazione di A è eliminato;
inoltre, il valore 67, memorizzato nella locazione di memoria VR
è assegnato alla variabile vmnel RDA di main
• La pila dei RDA è come mostrata in 5nella Fig. 5.1;
14. Si passa ad eseguire la prossima istruzione il cui indirizzo è
memorizzato nel program counter. Nell’esempio si passa ad
eseguire l’istruzione di indirizzo 104, che fa riprendere
l’esecuzione di main.
Unità 5 - Funzioni Pagina 54