introduzione al c unità 5 funzionisalza/fi-c/5-c-17-18.pdfmodalità, da tutti i moderni linguaggi...

54
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

Upload: others

Post on 24-Jul-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 2: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 3: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 4: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 5: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 6: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 7: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 8: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 9: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 10: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 11: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 12: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 13: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 14: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 15: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 16: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 17: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 18: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 19: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 20: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 21: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 22: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 23: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 24: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 25: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 26: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 27: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 28: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 29: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 30: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 31: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 32: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 33: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 34: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 35: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 36: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 37: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 38: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 39: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 40: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 41: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 42: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 43: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 44: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 45: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 46: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 47: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

2017/2018

Evoluzione della pila dei RDA

Figura 5.1

Unità 5 - Funzioni Pagina 47

Page 48: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 49: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 50: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 51: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 52: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 53: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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

Page 54: Introduzione al C Unità 5 Funzionisalza/FI-C/5-C-17-18.pdfmodalità, da tutti i moderni linguaggi di programmazione attuali (Java, C#, C++, C, Pascal, Fortran, Lisp, ecc.) Unità

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