Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 1
FONDAMENTI DI INFORMATICA
Prof. PIER LUCA MONTESSORO Ing. DAVIDE PIERATTONI
Facoltà di Ingegneria Università degli Studi di Udine
Le trappole del linguaggio C
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 2 Questo insieme d i 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 d i 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 a l 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 d i 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 i n progetti d i impianti, prodotti, reti, ecc. In ogni caso essa è soggetta a cambiamenti senza preavviso. Gli autori non assumono alcuna responsabilità per il contenuto d i 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
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 3
Le insidie del C
#include <stdio.h>
main() {
printf ("Hello world");
}
> cc -o hello.exe hello.c
> hello Hello world> _
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 4
"=" e "=="
if (x = y) /* ... */
Il codice viene eseguito se il valore di y, che viene assegnato alla variabile x, è diverso da 0.
if (x == y) /* ... */
Il codice viene eseguito se il valore di y è uguale a quello di x.
Fondamenti di Informatica -Linguaggio C - Le trappole del C
Analisi lessicale del programma
Esempi:
• a/*b è interpretato come a /* b, cioè come un commento aperto prima di b, e non come a / (*b), cioè come a diviso il dato indirizzato da b.
• a---b è interpretato come a-- - b, e non come a - --b.
Il compilatore C cerca sempre di costruire dei token di lunghezza massima.
Fondamenti di Informatica -Linguaggio C - Le trappole del C
Costanti intere
Se una costante inizia per 0 è interpretata come ottale.
struct {
int code;
char *description;
} code_table [] = {
023, "book", 072, "pencil", 112, "rubber"
};
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 7
La dichiarazione delle funzioni
• float g; variabile floating point g
• float f(); funzione che restituisce un valore float
• float *g; puntatore a float
• float *f(); funzione che restituisce un puntatore a float
• float (*f)(); puntatore a funzione che restituisce un valore float
• float *(*f)(); puntatore a funzione che restituisce un puntatore a float
Attenzione alla precedenza degli operatori!
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 8
Operatore di cast
Si mette tra parentesi la stessa espressione che si usa per la dichiarazione, ma senza l'identificatore della variabile.
float g; g = (float) x;
float *g; g = (float *) x;
float (*h)(); h = (float (*)()) x;
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 9
I tipi nei prototipi delle funzioni
Esempio: la funzione di libreria signal
void (*signal (int, void (*) (int))) (int);
Nel prototipo delle funzioni (ANSI C) si indicano i tipi degli argomenti esattamente come per il cast, ma senza le parentesi intorno.
puntatore a funzione che riceve un int come parametro e non restituisce nulla ( void )
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 10
Per usare i puntatori
Se puntatori a variabile:
float *g, f; f = *g;
Se puntatori a strutture:
list_element *lep;
lep = lep->next;
x = (*lep).data;
Se puntatori a funzioni:
float (*f)(), g; g = (*f)();
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 11
Precedenze degli operatori
Esempio:
if (flags & FLAGMASK != 0) non è equivalente a:
if (flags & FLAGMASK)
in quanto != ha la precedenza su &, e quindi risulta:
if (flags & (FLAGMASK != 0)) ovviamente sbagliato.
Non sempre sono quelle che ci si aspetta!
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 12
Precedenze degli operatori
L'operatore di shift è ancora più subdolo:
r = hi<<4 + low;
è interpretato come:
r = hi << (4 + low);
Due possibili versioni corrette sono:
r = (hi << 4) + low;
r = hi << 4 | low;
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 13
Precedenze degli operatori
Due osservazioni importanti:
- ogni operatore logico (es. && ) ha precedenza inferiore a qualsiasi operatore relazionale (es. >= ) - gli operatori di shift hanno precedenza minore degli
operatori aritmetici, ma maggiore di quelli logici.
Attenzione: " == " e " != " hanno precedenza inferiore degli operatori relazionali " > ", " < " ecc. Pertanto:
a < b == b < c significa (a < b) == (b < c)
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 14
Precedenze degli operatori
L'assegnazione viene raggruppata da destra verso sinistra:
home_score = visitor_score = 0;
è equivalente a:
visitor_score = 0;
home_score = visitor_score;
L'assegnazione ha anche minor precedenza degli operatori di relazione, e quindi nel caso seguente sono necessarie le parentesi:
while ((c = getc(file_ptr)) != EOF) ...
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 15
E il punto e virgola?
if (x[i] > big);
big = x[i];
Il compilatore accetta il ";" alla fine dell'if, e ignora l'indentazione. Quindi quanto scritto è equivalente a:
if (x[i] > big) { } big = x[i];
e non a:
if (x[i] > big) big = x[i];
!!!
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 16
E il punto e virgola?
Anche dimenticare un punto e virgola può essere pernicioso:
if (n < 3) return a[0] = p;
a[1] = q;
è interpretato come:
if (n < 3)
return a[0] = p;
a[1] = q;
Fondamenti di Informatica -Linguaggio C - Le trappole del C
Chiamata di funzione
Il C richiede che la chiamata di una funzione abbia sempre una lista di argomenti, eventualmente vuota:
f();
Tuttavia viene compilato senza errori anche:
f;
Questa espressione non chiama la funzione f, bensì ne calcola l'indirizzo, e poi lo butta via...
Fondamenti di Informatica -Linguaggio C - Le trappole del C
Else
else si riferisce sempre al più vicino if all'interno dello stesso blocco. Al solito, l'indentazione non è significativa!
if (a) if (b) f();
else
g();
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 19
Vettori
Possono essere solo unidimensionali.
Su un vettore si possono fare solo due cose:
- definirne la dimensione
- ottenere il puntatore all'elemento 0.
Tutte le altre operazioni sono realizzate mediante puntatori, anche se tramite una sintassi speciale:
v[5] è equivalente a *(v + 5)
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 20
Vettori bidimensionali
int calendar[12][31];
int *month;
int day;
Se si omette l'ultima dimensione si ottiene un vettore (il puntatore al primo elemento):
month = calendar[2];
day = month[30];
oppure
day = calendar[2][30];
o, ancora,
day = *(*(calendar + 2) +30);
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 21
char *r;
r = (char *) malloc
(strlen(s) + strlen(t) + 1);
strcpy (r, s);
strcat (r, t);
/* later... */
free (r);
I puntatori non sono vettori !
char *r;
strcpy (r, s);
strcat (r, t);
char r[100];
strcpy (r, s);
strcat (r, t);
Ancora meglio...
NO! OK
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 22
Conversione automatica di tipo
int strlen (char s[]) è equivalente a scrivere int strlen (char *s)
Tuttavia questo non si applica in altri contesti:
extern char *str;
non è equivalente a scrivere extern char str[];
come
char *str = "hello\n";
non è equivalente a
char str[] = "hello\n";
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 23
Attenzione ai limiti dei vettori
int a[10], i;
for (i = 1; i <= 10; i++) a[i] = 0;
Se la variabile i viene allocata dopo l'ultimo elemento del vettore, il programma entra in un loop infinito!
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 24
Ordine di valutazione
Il C garantisce l'ordine di valutazione delle espressioni (a differenza, per esempio, del Pascal).
Quindi si può scrivere:
if (count != 0 && sum/count < low_ awg) printf ("average < %g\n", low_avg);
senza ottenere un errore per divisione per zero se count == 0.
Uso tipico:
if (i < DIM && v[i] != 0) ...
non viene valutata se
si è raggiunta la fine
del vettore
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 25
Ordine di valutazione
Attenzione: non è definito l'ordine di valutazione per qualsiasi operatore.
Per esempio, in
if (f() < g())
può essere chiamata prima la funzione f o la funzione g indifferentemente.
I soli operatori per i quali è garantito l'ordine di valutazione sono:
&& || ?: ,
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 26
Variabili locali
char *strcat (char *s, char *t) {
char r[SIZE];
...
return r;
}
Quando la funzione termina, l'indirizzo della stringa r viene copiato come valore di ritorno, ma la stringa stessa è deallocata.
(Questo “bug” molto spesso non è individuabile durante l'esecuzione del programma...)
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 27
char *concatena (char str1[], char str2[]) {
int i, j;
char tmp[MAXSIZE];
for (i = 0; str1[i] != '\0'; i++) tmp[i] = str1[i];
for (j = i, i = 0;
str2[i] != '\0'; i++, j++) tmp[j] = str2[i];
return tmp;
}
Esempio
viene restituito il puntatore alla stringa, ma essa non esiste più
Fondamenti di Informatica -Linguaggio C - Le trappole del C
© 2001 Pier Luca Montessoro - Davide Pierattoni (vedere nota di copyright a pag. 2) 28