FONDAMENTI DI INFORMATICA
Prof. PIER LUCA MONTESSORO Ing. DAVIDE PIERATTONI
Facoltà di Ingegneria
Università degli Studi di Udine
Linguaggio C
Struttura dei programmi
Questo insieme di trasparenze (detto nel seguito slide) è protetto dalle leggi sul copyright e dalle disposizioni dei trattati internazionali. Il titolo ed i copyright relativi alle slides (ivi inclusi, ma non limitatamente, ogni immagine, fotografia, animazione, video, audio, musica e testo) sono di proprietà degli autori prof. Pier Luca Montessoro e ing. Davide Pierattoni, Università degli Studi di Udine.
Le slide possono essere riprodotte ed utilizzate liberamente dagli istituti di ricerca, scolastici ed universitari afferenti al Ministero della Pubblica Istruzione e al Ministero dell’Università e Ricerca Scientifica e Tecnologica, per scopi istituzionali, non a fine di lucro. In tal caso non è richiesta alcuna autorizzazione.
Ogni altro utilizzo o riproduzione (ivi incluse, ma non limitatamente, le riproduzioni su supporti magnetici, su reti di calcolatori e stampe) in toto o in parte è vietata, se non esplicitamente autorizzata per iscritto, a priori, da parte degli autori.
L’informazione contenuta in queste slide è ritenuta essere accurata alla data della pubblicazione. Essa è fornita per scopi meramente didattici e non per essere utilizzata in progetti di impianti, prodotti, reti, ecc. In ogni caso essa è soggetta a cambiamenti senza preavviso. Gli autori non assumono alcuna responsabilità per il contenuto di queste slide (ivi incluse, ma non limitatamente, la correttezza, completezza, applicabilità, aggiornamento dell’informazione).
In ogni caso non può essere dichiarata conformità all’informazione contenuta in queste slide.
In ogni caso questa nota di copyright e il suo richiamo in calce ad ogni slide non devono mai essere rimossi e devono essere riportati anche in utilizzi parziali.
Nota di Copyright
Lessico, sintassi, semantica
• Un programma è costituito da uno o più file di testo (o file sorgenti) contenenti un insieme di caratteri
• Come nel linguaggio naturale, in ogni linguaggio di programmazione si possono distinguere:
– il lessico, insieme dei simboli con cui è possibile scrivere un programma
– la sintassi, insieme delle regole di combinazione dei simboli
– la semantica, insieme delle regole di
interpretazione dei costrutti sintattici
Linguaggio e token
• Le “parole” del linguaggio naturale corrispondono ai token del linguaggio C
• Esistono sei classi di token:
– identificatori – parole chiave – costanti letterali – stringhe letterali – operatori
– separatori
• Gli spazi bianchi, i caratteri di tabulazione, i new line, i salti di pagina ed i commenti sono tutti dei
separatori di token.
Il compilatore e i token
• Quando il compilatore effettua l’analisi lessicale di un file sorgente, cerca sempre di individuare token di
lunghezza massima
• A partire da ogni separatore, il token successivo è quindi la più lunga sequenza di caratteri che può
costituire un token; ogni ambiguità può essere evitata utilizzando gli spazi bianchi
• Esempio: l’espressione con operatori aritmetici x=y---z;
sarà interpretata dal compilatore come...
x = (y--) - z;
Formato del linguaggio
• Il C è un linguaggio a formato libero
• La separazione tra gli elementi sintattici si basa sulla presenza di parole chiave e simboli separatori
• Il cambio di riga è equiparato ad uno spazio
→
versatilità di scrittura e leggibilità dei programmi#include <stdio.h>
#include <stdlib.h>
/* programma principale */
int main() {
printf ("Ciao, mondo!");
return EXIT_SUCCESS;
}
/* fine del programma */
#include <stdio.h>
#include <stdlib.h>
/* programma principale */
int main(){printf (
"Ciao, mondo!"); return EXIT_SUCCESS;}/* fine del programma */
Il programma è ugualmente corretto, ma risulta illeggibile!
Stile di programmazione
• In C non viene imposto alcuno stile di programmazione
• È compito del programmatore adottare uno stile chiaro, in modo da rendere comprensibile a sé e agli altri il
codice prodotto
• È buona norma:
– scrivere una sola istruzione per ciascuna riga
– usare spazi per separare anche visivamente i token – indentare i blocchi di codice mediante 3 spazi
(evitare il carattere di tabulazione)
– utilizzare dei commenti a corredo delle istruzioni più difficilmente comprensibili
Indentazione
• L’indentazione è una tecnica di scrittura molto utile nel caso di programmi dalla struttura complessa
• Fa uso di spazi di rientro per isolare gruppi di istruzioni in sottolivelli logici: {
istruzione_1 istruzione_2
…
istruzione_14 {
istruzione_15 {
istruzione_16
…
istruzione_32 }
istruzione_33 istruzione_34 }
istruzione_35 istruzione_36 }
Annidamento dei blocchi di codice
Standard proposto: 3 spazi
Commenti
• I caratteri /* introducono una o più righe di commento, terminato con i caratteri */
• Il compilatore ignora tutti i caratteri compresi tra i delimitatori /* e */
printf ("Ciao, mondo!"); /* questo è un
commento: stampa sullo standard output la stringa
"Ciao, mondo!" */
• I commenti non possono essere annidati; non è lecito quindi scrivere:
/* questo è un primo commento
/* questo è un secondo commento */
e questa è la continuazione del primo */
Identificatori
• Gli identificatori sono delle sequenze di caratteri che rappresentano genericamente degli elementi
• Un identificatore può contenere lettere (maiuscole e minuscole), cifre e il carattere "_" (underscore)
• Non può contenere spazi, simboli separatori, simboli di operatori (es. + , - , % , & , . (punto) , ,
(virgola) )
• Deve iniziare con una lettera oppure con l’underscore
• Pippo1, pippo_e_pluto e _pippo sono validi
• b 52, acme&c, Donald.Duck non sono validi
• Normalmente i compilatori ammettono una lunghezza massima per un identificatore di 32 caratteri
Identificatori
• Il linguaggio C è case sensitive Æ lettere maiuscole e lettere minuscole sono interpretate come codici
diversi anche negli identificatori
• Gli identificatori:
Pippo pippo pIpPO PIPPO
sono interpretati come diversi fra loro
• Questo aspetto consente di combinare più parole in un solo identificatore, per facilitare la lettura del
codice:
DonaldDuck NumeroDiElementi
Struttura di un programma
• Un programma C è un insieme di funzioni
• Ogni funzione è un blocco di codice contenente un insieme di istruzioni racchiuse tra le parentesi graffe, { e } , a cui è associato un nome, nella forma:
nomefunzione (…) {
istruzione_1;
istruzione_2;
…
istruzione_n;
}
• Ciascun blocco di codice è sintatticamente equivalente a una singola istruzione
Struttura di un programma
• La dichiarazione int main () individua la funzione principale di un programma
• La definizione della funzione main consiste poi in una serie di istruzioni (o statement) racchiuse in un blocco di codice interno, costituente il corpo del
programma
int main () {
printf ("Ciao, mondo!\n");
return EXIT_SUCCESS;
}
• La forma minima di un programma C è dunque:
int main () {}
Struttura di un programma
• Il corpo del programma è l’insieme delle istruzioni che il programma deve eseguire
• Questo blocco consta di due parti:
un primo set di istruzioni dichiarative, che determinano variabili e tipi di dati
una sequenza di istruzioni operative, ovvero le azioni svolte di fatto dal programma
(input/output, assegnazioni di valori, valutazione di espressioni)
• Ogni istruzione è terminata dal carattere punto e virgola ;
Struttura di un programma
• Il seguente programma definisce una variabile intera i, visualizza un messaggio operativo per l’utente, legge un numero da tastiera e ne stampa il valore sullo
schermo:
#include <stdio.h>
#include <stdlib.h>
int main() {
/* istruzione dichiarativa */
int i;
/* istruzioni operative */
printf ("Digita il numero: ");
scanf ("%d", &i);
printf ("Valore digitato: %d\n", i);
return EXIT_SUCCESS;
Funzioni di input/output
• Nel programma compaiono alcune funzioni, dette funzioni di libreria, che eseguono operazioni di input/output
• scanf è una funzione che legge un carattere da tastiera (lo standard input), ne converte il valore
secondo il formato specificato e lo attribuisce ad una variabile
scanf ("%d", &i);
Indirizzo della variabile i in memoria (operatore &)
Interpreta il dato letto da tastiera come un intero ("%d"), un numero reale ("%f"), un carattere ("%c") ...
Funzioni di input/output
• printf è una funzione di libreria che stampa sul monitor (lo standard output) una stringa costante:
printf ("Hello world!");
oppure il valore di una variabile di tipo specificato:
printf ("%d", i);
Interpreta il dato contenuto nella variabile come un intero ("%d"), un numero reale ("%f"), un carattere ("%c") ...
Espressione
contenente il nome della variabile
Comandi del preprocessor
• I programmi C più semplici sono organizzati secondo lo schema:
<direttive del preprocessor>
int main() {
<istruzioni dichiarative>
<istruzioni operative>
}
• Il preprocessor costituisce la prima fase di analisi del codice sorgente, e precede l’attività di compilazione vera e propria
• Il preprocessor elimina anche i commenti
Comandi del preprocessor
• Tutte le direttive destinate al preprocessor sono denotate dal simbolo # come primo carattere di una riga
• L’istruzione #include <nomefile.h> comanda l’inclusione di un file di libreria (header file) nel codice sorgente
• Il file stdio.h è un file di libreria necessario per poter utilizzare le funzioni di I/O
• Il file stdlib.h è un file di libreria necessario per
utilizzare alcune funzioni e per definire alcune costanti di sistema (tra cui EXIT_SUCCESS)
• Non contiene istruzioni esecutive, ma solo dichiarazioni di funzioni, costanti tipi di dato e macroistruzioni
Analisi lessicale di un programma
• Consideriamo un semplice programma che somma due numeri e scrive il risultato sullo standard output (il
monitor); proviamo ora ad analizzarlo secondo la prassi del compilatore...
• Il significato delle indicazioni è il seguente:
– identificatori – parole chiave – costanti letterali – stringhe letterali – operatori
– separatori
– commenti e direttive al preprocessor
Analisi lessicale di un programma
#include <stdio.h>
#include <stdlib.h>
/* programma principale */
int main() {
int a, b;
scanf ("%d %d", &a, &b); /* legge a e b */
printf ("a+b=%d\n", a + b);
/* istruzione di ritorno al sistema operativo */
return EXIT_SUCCESS;
} /* fine del programma */
Analisi lessicale di un programma
#include <stdio.h>
#include <stdlib.h>
/* programma principale */
int main() {
int a, b;
scanf ("%d %d", &a, &b); /* legge a e b */
printf ("a+b=%d\n", a + b);
/* istruzione di ritorno al sistema operativo */
return EXIT_SUCCESS;
} /* fine del programma */