Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
TIPI DI DATO PRIMITIVI
• caratteri:
char caratteri ASCII (1 byte);
o
• interi con segno:
short [int] -32768 ... 32767 (2 byte);
o int -2147483648 ... 2147483647 (4 byte);
o long [int] -231 ... 231-1 (8 byte);
o
• naturali (interi senza segno):
unsigned short [int] 0 ... 65535 (2 byte);
o unsigned [int] 0 ... 4294967295 (4 byte);
o unsigned long [int] 0 ... 264 -1 (8 byte);
o
• reali: float singola precisione (4 byte);
o double doppia precisione (8 byte);
o
• boolean:
non esistono in C come tipo primitivo;
o si usano gli interi:
o zero indica FALSO;
§ uno indica VERO (ogni altro valore indica vero);
§
33
Una stringa è una collezione di caratteri delimitata da virgolette "ciao" "Hello\n"
In C le stringhe sono semplici sequenze di caratteri di cui l’ultimo, sempre presente in modo
implicito, è '\0' "ciao" = {'c', 'i', 'a', 'o', '\0'}
Il C è un linguaggio basato su espressioni, un’espressione è una notazione che denota un
valore mediante un processo di valutazione, un’espressione può essere semplice o composta
(tramite aggregazione di altre espressioni).
ESPRESSIONI E OPERATORI RELAZIONALI
uguaglianza ==
diversità !=
maggiore di >
minore di <
maggiore o uguale a >=
minore o uguale a <=
not (negazione) !
and &&
or ||
la valutazione dell’espressione cessa appena si è in grado di determinare il risultato (il
secondo operando è valutato solo se necessario)
Es. a && b && c
se a&&b è falso, il secondo && non viene neanche valutato
Una espressione condizionale è introdotta dall’operatore ternario condiz ? espr1 : espr2
L’espressione denota:
il valore denotato da espr1 se condiz è vera;
■ Il valore denotato da espr2 se condiz è falsa.
■
Priorità e associatività sono le proprietà predefinite che però possono essere alterate
mediante l’uso di parentesi. 34
35
Lezione 13- Variabili e funzioni
La parte <main> è l’unica obbligatoria, è una particolare <unità di traduzione> (funzione) ed è
definita dalla produzione:
<main> ::=
main(){
[<dichiarazioni-e-definizioni>]
[<sequenza-istruzioni>]
}
<dichiarazioni-e-definizioni> introducono i nomi (identificatori) di costanti, variabili, tipi
definiti dall’utente.
<sequenza-istruzioni> sequenza di frasi del linguaggio ognuna delle quali è un’istruzione.
Una variabile è un’astrazione della cella di memoria. Formalmente, è un simbolo associato a
un indirizzo fisico e che denota un valore.
int x; /* x deve denotare un valore intero */
float y; // y deve denotare un valore reale
char ch, ch1; /* ch e ch1 entrambi char */
double p; //p deve denotare un valore double
int x1; // di nuovo un valore intero
int x2; char ch3; //sulla stessa riga
Quindi, una variabile può comparire in una espressione e denota un valore pari al suo R-value
CARATTERISTICHE DELLE VARIABILI
• campo d’azione (scope o visibilità): è la parte di programma in cui la variabile è nota e
può essere manipolata;
• tipo: specifica la classe di valori che la variabile può assumere (e quindi gli operatori
applicabili);
• tempo di vita (lifetime): è l’intervallo di tempo in cui rimane valida l’associazione
simbolo/indirizzo fisico (L-VALUE);
• valore: è rappresentato (secondo la codifica adottata) nell’area di memoria associata
alla variabile;
Una funzione è un componente software che cattura l’idea matematica di funzione
f : A × B × ... × Q → S
Una funzione riceve dati di ingresso in corrispondenza ai parametri, ha come corpo una
espressione, la cui valutazione fornisce un risultato e denota un valore in corrispondenza al
suo nome. 36
Una funzione è un servitore passivo che serve un cliente per volta ma che può trasformarsi in
cliente invocando sé stessa o altre funzioni.
Una funzione è un servitore dotato di nome che incapsula le istruzioni che realizzano un certo
servizio.
Per chiedere al servitore di svolgere il servizio occorre chiamare tale servitore (per nome) e
fornirgli le informazioni necessarie.
Cliente e servitore comunicano mediante l’interfaccia della funzione (comprende nome della
funzione, lista dei parametri e tipo del valore da essa denotato), ed è spesso chiamata firma
(signature) perché esplicita il contratto di servizio fra cliente e servitore.
Cliente e servitore comunicano quindi mediante i parametri trasmessi dal cliente al servitore
all’atto della chiamata (direzione: dal cliente al servitore), il valore restituito dal servitore al
cliente (direzione: dal servitore al cliente)
La conoscenza di cosa un simbolo denota viene espressa da una legame (binding) tra il
simbolo e uno o più attributi. La collezione dei binding valida in (un certo punto di) un
programma si chiama environment.
La parte nel testo di un programma (cioè tutti i simboli) a cui si applica un dato binding si dice
portata o scope del binding La parte nel testo di un programma (cioè tutti i simboli) a cui si
applica un dato binding si dice portata o scope del binding.
Le regole in base a cui si stabilisce la portata di un binding si dicono regole di visibilità o
scope rules. La definizione di una funzione introduce un nuovo binding nell’environment in
cui la funzione è definita (in C: global environment). Al momento dell’invocazione, si crea un
nuovo environment ovvero una struttura dati che contiene i binding dei parametri e degli
identificatori definiti localmente alla funzione.
MEMORIA: AREA DATI
• Area dati globali: Contiene le variabili libere (non definite dentro a una funzione);
• Heap: Area destinata alle variabili dinamiche;
• Stack: Contiene i record di attivazione (frame) delle funzioni.
È il “mondo della funzione”: contiene tutto ciò che ne caratterizza l’esistenza:
i parametri ricevuti;
o le variabili locali;
o l’indirizzo di ritorno;
o punto a cui tornare (nel codice del cliente) al termine della funzione
o (istruzione successiva alla chiamata);
un collegamento al record di attivazione del cliente;
o per permettere al cliente di tornare al suo mondo.
o
37
Il record di attivazione rappresenta il “mondo della funzione”: nasce e muore con essa, è
creato al momento della invocazione di una funzione, permane per tutto il tempo in cui la
funzione è in esecuzione ed è distrutto (deallocato) al termine della esecuzione della funzione
stessa.
Ad ogni chiamata di funzione viene creato un nuovo record, specifico per quella chiamata di
quella funzione. La dimensione del record di attivazione varia da una funzione all’altra, per
una data funzione, è fissa e calcolabile a priori.
Funzioni che chiamano altre funzioni danno luogo a una sequenza di record di attivazione
(allocati secondo l’ordine delle chiamate e deallocati in ordine inverso). La sequenza dei link
dinamici costituisce la cosiddetta catena dinamica, che rappresenta la storia delle attivazioni
(“chi ha chiamato chi”).
Per catturare la semantica delle chiamate annidate (una funzione che chiama un’altra
funzione che...), l’area di memoria in cui vengono allocati i record di attivazione deve essere
gestita come una pila (stack). Una struttura dati gestita con politica LIFO (Last In, First Out -
l’ultimo a entrare è il primo a uscire).
MODELLO APPLICATIVO DELLE FUNZIONI
1. Valutazione, nell’environment corrente, del simbolo che denota il nome della
funzione;
2. Valutazione, nell’environment corrente, delle espressioni che denotano i parametri
attuali;
3. Chiamata della funzione con passaggio dei parametri e commutazione
all’environment di definizione della funzione;
4. Esecuzione del corpo della funzione (nel suo environment di definizione);
5. Restituzione al chiamante di controllo risultato con ripristino dell’environment
e
esistente al momento della chiamata.
Il cliente passa informazioni al servitore mediante una serie di parametri attuali.
Parametri formali:
sono specificati nella dichiarazione del servitore
o esplicitano il contratto fra servitore e cliente
o indicano cosa il servitore si aspetta dal cliente
o
Parametri attuali:
sono trasmessi dal cliente all’atto della chiamata;
o devono corrispondere ai parametri formali in numero, posizione e tipo.
o
I parametri attuali sono legati ai parametri formali al momento della chiamata, in modo
e
dinamico. Tale legame: vale solo per l’invocazione corrente per la durata della funzione. 38
In generale, un parametro può essere trasferito: per valore (by value) quando si trasferisce il
valore del parametro attuale(viene anche chiamato copia) o per riferimento (by reference)
ovvero quando si trasferisce un riferimento al parametro attuale.
Passaggio per valore: Ogni azione fatta su w è
strettamente locale al
servitore.
Passaggio per riferimento: Ogni azione fatta su w è in
realtà fatta sulla variabile z
del cliente.
In C, i parametri sono trasferiti sempre e solo per valore (by value) e si trasferisce una copia
del parametro attuale, non l’originale! Tale copia è strettamente privata e locale a quel
servitore, il servitore potrebbe quindi alterare il valore ricevuto, senza che ciò abbia alcun
impatto sul cliente. Conseguenza: per trasferire un’informazione dal servitore al cliente si
sfrutta il valore di ritorno della funzione.
C adotta sempre e solo il passaggio per valore per due motivi: è sicuro (e variabili del
chiamante e del chiamato sono completamente disaccoppiate) e consente di ragionare per
componenti e servizi (la struttura interna dei singoli componenti è irrilevante). I limiti invece
sono la capacità di restituire al cliente solo valori di tipo semplice e il fatto che non consenta
di restituire collezioni di valori (array).
DICHIARAZIONE E DEFINIZIONE DI UNA FUNZIONE
La definizione di una funzione costituisce l’eqettiva realizzazione del componente. La
dichiarazione specifica il contratto di servizio fra cliente e servitore, esprimendo le proprietà
essenziali della funzione. La dichiarazione specifica: il nome della funzione, numero e tipo dei
parametri (non necessariamente il nome) il tipo del risultato.
e
39
La definizione di una funzione costituisce l’eqettiva realizzazione del componente. La