Appunti sul linguaggio C

Transcript

Appunti sul linguaggio C
Appunti sul linguaggio C
Diapositive adattate dalle omonime create dalla
Dottoressa di Ricerca Giovanna Melideo per il corso
di Laboratorio di Algoritmi e Strutture Dati
04/05/2005
LP2-04/05 - Appunti di C
1
Il processo di compilazione
Il comando di compilazione dunque richiama:
• Il preprocessore
modifica una copia del file sorgente (secondo le direttive
contenute in esso) producendo una “unità di traduzione”
traduzione
• Il compilatore
traduce la “unità” in codice oggetto se non rileva errori
(tipicamente errori sintattici)
• Il linker
Crea il file eseguibile dal codice oggetto prodotto dal
compilatore ed il codice oggetto disponibile nelle librerie di
sistema
• Attenzione agli errori logici, non rilevabili in fase di
compilazione !
04/05/2005
LP2-04/05 - Appunti di C
2
Struttura di un programma
Un programma C è costituito da:
• Inclusione di librerie e definizione di costanti tramite
le direttive al preprocessore #include e #define
• Definizione di variabili globali
• Dichiarazioni di funzioni (o prototipi)
• Definizione di funzioni
• Una funzione main() da cui ha inizio l’esecuzione
del programma
04/05/2005
LP2-04/05 - Appunti di C
3
Direttive al preprocessore
• Mediante la direttiva #include è possibile indicare le
librerie da “caricare”:
– una copia del file header è inclusa nel codice prima
della compilazione
• La direttiva #include può indicare l’inclusione di:
– file header standard (#include <stdio.h>), oppure
– file header definiti dall’utente (#include
“myfile.h”)
04/05/2005
LP2-04/05 - Appunti di C
4
Direttive al preprocessore
• Mediante la direttiva #define è possibile definire
le costanti simboliche
Es.:
#define PI 3.1415
ogni occorrenza di “PI” è sostituita dal
preprocessore con 3.1415,
3.1415 ad eccezione delle
occorrenze nelle stringhe racchiuse da
virgolette e nei commenti
04/05/2005
LP2-04/05 - Appunti di C
5
Dichiarazioni di variabili
• Una variabile rappresenta un’associazione tra un nome ed un
valore. Per “tipo” si intende un insieme di valori ed un insieme
di operazioni definite su di essi
• In C, come per ogni linguaggio che possiede il controllo dei
tipi, ogni variabile deve essere dichiarata prima del suo
utilizzo per permettere il controllo della consistenza
• Le variabili dichiarate al di fuori delle funzioni (variabili globali)
hanno una validità globale sull’intero programma e possono
essere utilizzate da tutte le funzioni.
• L’uso di variabili globali contribuisce a diminuire la portabilità
e la riutilizzabilità delle funzioni ed è pertanto sconsigliato
04/05/2005
LP2-04/05 - Appunti di C
6
Dichiarazione di funzioni
• La possibilità di definire funzioni consente di
frammentare il programma in tanti moduli
• se la suddivisione rispecchia la
frammentazione del problema in sottoproblemi più semplici ed elementari il
programma assume una architettura
modulare e il riuso delle funzioni è più
semplice
04/05/2005
LP2-04/05 - Appunti di C
7
La funzione main()
• La funzione main() è una particolare funzione che
viene eseguita automaticamente dal programma
quando questo viene lanciato
Ø main() è il punto di inizio del programma
• Il valore restituito dalla funzione main() (un intero,
come richiesto dallo standard ANSI-C) può essere
utilizzato come codice di controllo da un eventuale
programma chiamante
04/05/2005
LP2-04/05 - Appunti di C
8
Regole sintattiche principali
• Il linguaggio C è case-sensitive:
sensitive il compilatore distingue fra lettere
minuscole e maiuscole.
• Ogni istruzione è terminata da un punto-e-virgola (“;”).
• I blocchi di istruzioni sono racchiusi da parentesi graffe (“{” e “}”) e
contengono una parte opzionale di dichiarazioni seguita da una
sequenza di istruzioni.
• I commenti sono racchiusi tra “/*” e “*/” .
• I nomi delle funzioni e delle variabili sono costituiti solo da caratteri
alfa-numerici e dal simbolo di sottolineatura (underscore: “_”) e non
devono iniziare con un carattere numerico. Es.: “B”, “ciao”, “CiAo”,
“_nome”, “Nome17” .
• Convenzione: usare nomi con minuscole per variabili e funzioni,
maiscole per le costanti
04/05/2005
LP2-04/05 - Appunti di C
9
Regole sintattiche principali
• Una dichiarazione di variabili avviene riportando il tipo di dato seguito
dall’elenco dei nomi di variabile separati da virgole “,”. Nella
dichiarazione le variabili possono essere inizializzate. Es: char x,
_pi2=‘a’, A123b;
• Non è possibile definire funzioni all’interno del corpo di altre funzioni.
• I parametri “formali” di una funzione vengono specificati tra parentesi
tonde e separati tra loro mediante la virgola.
• Una funzione viene attivata mediante la chiamata, che provvede al
passaggio degli eventuali parametri “attuali” che devono corrispondere
in numero, ordine e tipo con quelli formali specificati nella
dichiarazione.
• La chiamata di funzioni con dominio nullo deve comunque essere
effettuata riportando le parentesi tonde dopo il nome della funzione.
Es.: “saluti();” .
04/05/2005
LP2-04/05 - Appunti di C
10
Esempio
#include <stdio.h> /* direttive al */
#define PI 3.1415 /* preprocessore */
float area(int);
/* prototipo
*/
int main (void){
float y;
/* float: tipo dei razionali */
y=area(5);
/* chiamata di funzione
*/
return 0;
}
float area(int raggio) {
/* fine definizione */
return (raggio* raggio * PI);
}
/* fine definizione */
04/05/2005
LP2-04/05 - Appunti di C
11
Tipi di dato elementari
• Il C fornisce al programmatore tipi di dato
elementari con cui definire variabili e funzioni:
Numeri interi
int
interi relativi
Numeri razionali
float
double
char
reali in precisione singola
reali in precisione doppia
Caratteri
p
p
caratteri alfanumerici
La parola chiave void denota l’insieme vuoto.
Per dichiarare il tipo delle variabili si deve riportare il nome del tipo
seguito dai nomi delle variabili separati da virgole.
Es: int _A2b, x4;
04/05/2005
LP2-04/05 - Appunti di C
12
Tipo di dato int
• L’insieme dei valori è costituito da numeri interi
compresi tra i valori INT_MIN e INT_MAX definiti
nella libreria standard <limits.h>
• INT_MAX è il massimo intero rappresentabile in una
parola di macchina: in una architettura a 32 bit, un
int occupa 4 byte e INT_MAX vale 2311=2.147.483.647
• I principali operatori tra valori interi sono gli
operatori aritmetici (+, -, *, /) e l’operatore di
modulo (%) descritti in seguito.
04/05/2005
LP2-04/05 - Appunti di C
13
Tipi di dato float e double
• Com’è noto, i numeri reali, come definiti in matematica, non sono
rappresentabili sui calcolatori
• I tipi in virgola mobile assumono valori in un sottoinsieme dei
razionali detto insieme dei numeri di macchina (perché dipende
strettamente dalla macchina su cui è implementato il compilatore).
Nella libreria <float.h> sono definiti i valori:
Ø FLT_MIN,FLT_MAX (risp. DBL_MIN,DBL_MAX): minimo
valore positivo e massimo valore float (double) rappresentabile
Ø FLT_EPSILON (risp. DBL_EPSILON): la precisione di
macchina, ovvero il minimo float (double) ε tale che 1+ ε ≠ε
Ø In una architettura a 32 bit FLT_EPSILON vale 10-7 e
DBL_EPSILON vale 10-15
• I principali operatori tra valori reali sono gli usuali operatori aritmetici
• Le costanti si indicano con il punto decimale e/o l’esponente (1.2e-2)
04/05/2005
LP2-04/05 - Appunti di C
14
Tipo di dato char
• L’insieme dei valori è costituito dai caratteri normalmente visibili su
schermo più alcuni caratteri speciali.
• I valori costanti “stampabili” sono rappresentati fra apici singoli (es:
‘a’, ‘G’, ‘3’, ‘&’).
– Si noti che ‘G’ è diverso da ‘g’ e che ‘3’ è diverso dall’intero 3.
• I caratteri speciali possono essere rappresentati in forma simbolica
mediante backslash “\” seguito da un carattere o dal codice ottale
del carattere. Ad es:
–
–
–
–
–
–
costante null;
‘\007’ è ‘\’’ è l’apice e ‘\”’ è il doppio apice;
‘\n’ è il carattere di controllo newline (a capo);
‘\t’ è il carattere di tabulazione;
‘\0’ è la il bel (segnale acustico)
‘\x20’ è il carattere di codice esadecimale 20 (32 in decimale)
04/05/2005
LP2-04/05 - Appunti di C
15
Tipo di dato char
• Secondo la codifica ASCII:
Ø
Ø
Ø
Ø
I codici delle cifre da ‘0’ e ‘9’ sono consecutivi;
lettere dalla ‘A’ alla ‘Z’ sono consecutive;
lettere dalla ‘a’ alla ‘z’ sono consecutive;
La differenza tra il codice di una lettera maiuscola e quello della
lettera minuscola corrispondente è 32.
• Il tipo char è a tutti gli effetti un tipo intero di solito rappresentato
da un singolo byte e su cui si possono effettuare le operazioni
previste sugli interi. Ad es.:
Ø è lecito scrivere ‘a’+4 per rappresentare il quarto carattere che
segue ‘a’.
Ø ‘a’-’A’ vale 32
04/05/2005
LP2-04/05 - Appunti di C
16
Costanti di enumerazione
Sono un modo comodo per assegnare nomi alle costanti. Esempi:
• enum boolean { NO, YES }; /*assegna NO a 0 e YES a 1*/
• enum numeri { zero, uno, due };
• enum numeri_grandi { cento = 100, centouno, centodue };
• enum numeri_magici { INTREQ = \x9c, DMACON = \x96,
BEAMCON0 = \x1dc, AUD0PER = \xa6 };
04/05/2005
LP2-04/05 - Appunti di C
17
I modificatori
• Il C permette di definire varianti dei tipi aritmetici mediante l’uso dei
modificatori short, long, signed, unsigned, che possono
precedere il tipo nelle dichiarazioni di variabili
• I modificatori variano l’occupazione di memoria o il campo dei valori
ammissibili:
– short tipicamente diminuisce l’occupazione;
– long tipicamente aumenta l’occupazione;
– signed denota l’esistenza del segno
– unsigned denota l’uso del bit di segno, per cui l’intervallo di
rappresentazione è tutto positivo
• Non è vero che a tutte le combinazioni corrispondono
rappresentazioni distinte. Es.: signed int equivale a int
• Il risultato dell’applicazione di short e long dipende
dall’implementazione
04/05/2005
LP2-04/05 - Appunti di C
18
Valori di verità e valori stringa
• In C89 non esiste un tipo specifico per i valori di verità “vero” e
“falso” come il tipo boolean del Pascal. Nel C99 è stato introdotto il
tipo _Bool composto da 0 (interpretato come “falso” nella valutazione
di una condizione) e 1 (“vero”). La convenzione adottata in C89 è che
0 rappresenta “falso” e un qualunque intero diverso da 0 rappresenta
“vero”
• Il C non prevede il tipo di dato stringa: questo significa che non è
possibile dichiarare una stringa come si dichiara un carattere o un
valore numerico
• Una costante stringa è rappresentata come una sequenza di caratteri
racchiusa da doppi apici. Es: “sono una stringa”
04/05/2005
LP2-04/05 - Appunti di C
19
Operatori
• Operatori aritmetici
“+”, “-”, “*”, “/”, “%” (operatore di modulo, solo per interi)
Ø Conversione implicita di tipo: se un operatore è applicato ad
operandi di tipo diverso il C effettua la conversione verso il tipo
più generale (es: 3/2 vale 1; 3.0/2=1.5)
Ø Gli operatori “+” e “-” sono applicabili anche ad operandi di
tipo char (es: lett+’a’-’A’)
• Operatori logici di confronto
“==“, “!=“, “<“, “>”, “<=”, “>=”
Ø Applicabili anche ad operandi di tipo char (es: ‘a’<‘b’)
04/05/2005
LP2-04/05 - Appunti di C
20
Operatori
• Operatori booleani
“!” (not), “&&” (and), “||” (or)
Ø Per convenzione è falsa ogni espressione che vale 0,
vera ogni altra.
Ø Le espressioni logiche sono valutate da sinistra verso
destra e la valutazione si interrompe non appena è
possibile stabilire un valore con certezza aritmetici
• Operatore di assegnamento
Ø forma estesa: a=b*c; x=-234.5;
Ø forma contratta: x <op>= y; (<op>=+,-,*,/), che
equivale a x=x <op> y;
Ø operatore come espressione: a=b=c=d+1; Equivale
alla sequenza: c=d+1; b=c; a=b;
04/05/2005
LP2-04/05 - Appunti di C
21
Operatori legati ai tipi
• Type-casting
l’operatore cast permette la modifica esplicita dei tipi
(<tipo>) <espr>
•
Es: (int) 5.4
Conversioni automatiche:
n_intero=(int) n_float; /* assegna la parte intera di un “reale” */
n_intero=(int) lettera; /* assegna il codice ASCII del carattere*/
n_float=(float) n_intero /* converte in “reale” l’intero*/
04/05/2005
LP2-04/05 - Appunti di C
22
Operatori legati ai tipi
• Operatore-funzione sizeof()
sizeof(<tipo>)
(equivalentemente: sizeof(<var>))
sizeof(T) restituisce l’occupazione in byte di una variabile di
tipo T
La dimensione dei tipi fondamentali può variare da una macchina ad
un’altra. Comunque vale quanto segue:
sizeof(char) vale 1
sizeof(short) ≤ sizeof(int) ≤ sizeof(long)
sizeof(signed) = sizeof(unsigned) = sizeof(int)
sizeof(float) ≤ sizeof(double) ≤ sizeof(long
double)
04/05/2005
LP2-04/05 - Appunti di C
23
Altri operatori
• Operatore condizionale
– operatore ternario i cui operandi sono un’espressione logica e
due espressioni di tipo qualsiasi:
<espr-logica> ? <espr1> : <espr2>;
– Il valore è restituito dall’espressione condizionale è:
• il valore restituito da <espr1> se l’espressione logica ha
valore “vero” (!= 0)
• il valore restituito da <espr2> altrimenti.
04/05/2005
LP2-04/05 - Appunti di C
24
Altri Operatori
•
Operatori per manipolare i bit
–
“&” AND bit a bit
–
“|” OR inclusivo bit a bit
–
“^” OR esclusivo bit a bit
–
“~” NOT bit a bit
–
“<<“ shift a sinistra
–
“>>” shift a destra
•
Esempi
–
\x0f & \xab == \x0b, \x55 | \xaa == \xff, \x0f == (~\xf0)
–
\x2b >> 1 == \x15, \x2b << 2 == \xa8
04/05/2005
LP2-04/05 - Appunti di C
25
Esempio
Il calcolo del massimo tra due numeri in virgola mobile
float max(float a, float b) {
float x;
float max(float a, float b {
x=(a>b) ? a : b;
return (a>b) ? a : b;
return x;
}
}
float max(float a, float b {
/* assegnamento contestuale
alla
dichiarazione della var */
float x=(a>b) ? a : b;
return x;
}
04/05/2005
LP2-04/05 - Appunti di C
26
Altri operatori
• Operatore di incremento “++” e decremento “--”
/* x vale 4 */
Ø int x=3; x++;
Ø char x=‘a’; ++x;
/* x vale ‘b’ */
• è importante sottolineare che un'istruzione del tipo x++; è più
veloce della corrispondente x=x+1;
• Attenzione all’interno di espressioni:
– se postposti, l’incremento/decremento viene effettuato dopo la
valutazione dell’espressione
– Se preposti, l’incremento/decremento viene effettuato prima della
valutazione dell’espressione
04/05/2005
LP2-04/05 - Appunti di C
27
Esempi
n
Esempio 1
int x,z=2;
x=(++z)-1; /* A questo punto x=2 e z=3 */
x=(z++)-1; /* A questo punto x=1 e z=3 */
n
Esempio 2
Ø x=((++z)-(w--))%100;
equivale alle seguenti istruzioni:
z++;
x=(z-w)%100;
w--;
04/05/2005
LP2-04/05 - Appunti di C
28
La precedenza tra operatori
• Una espressione complessa si presta ad essere interpretata in modi
diversi.
• Le ambiguità sorgono su:
Ø L’ordine di applicazione degli operatori. Esempio: l’espressione
3+2*5 dovrebbe essere intesa come 3+(2*5) e non (3+2)*5
Ø L’associatività degli operatori. Esempio: l’espressione 9/3/2 va
intesa come (9/3)/2 o 9/(3/2) ?
• Il C fissa univocamente sia la precedenza che l’associatività degli
operatori
04/05/2005
LP2-04/05 - Appunti di C
29
Ordine di precedenza tra operatori
• Di seguito vengono riportati in ordine decrescente di precedenza
tutti gli operatori incontrati con la loro associatività
Ø ++, --, (<tipo>), *
(da destra a sinistra)
Ø *, /, %
(da sinistra a destra)
Ø +, (da sinistra a destra)
Priorità alta
Ø <, <=, >, >=
(da sinistra a destra)
Ø ==, !=
(da sinistra a destra)
Ø &
(da sinistra a destra)
Ø !
(da sinistra a destra)
Ø &&
(da sinistra a destra)
Ø ||
(da sinistra a destra)
Ø ?:
(da destra a sinistra)
Ø =, <op>=
(da destra a sinistra)
Priorità bassa
04/05/2005
LP2-04/05 - Appunti di C
30