Università dell’Insubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2004/05 Laboratorio di Linguaggi lezione IV Marco Tarini Laboratorio di Linguaggi • docente: Marco Tarini e-mail: [email protected] • ricevimento: Martedì 14:30 - 17:30 o anche su appuntamento • libro di testo consigliato: Kelley Al, Pohl Ira: "C Didattica e Programmazione" ("A Book on C") quarta edizione - anche la terza va bene Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: operazioni a basso livello Esercizio: un numero in virgola mobile a doppia precisione di solito, ma dipende dall'implementazione • Sappiamo che un double occupa 8 bytes. • Dato un double, quale è il valore di questi 8 bytes? • Per esempio, quali 8 bytes compongono il valore 3.14159256 ? Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: operazioni a basso livello • A casa, provate questo programma, e scopriamo: – quali sono gli 8 bytes che compongono il double 3.14159256 – quali sono gli 8 bytes che compongono il double 6.022 x 1023 • e, adattando il programma agli interi: – quali sono i 4 bytes che compongono l'int +1000000 – quali sono i 4 bytes che compongono l'int +1 – quali sono i 4 bytes che compongono l'int -1 • a seconda di quale architettura viene usata, potremmo trovare risposte diverse! – domanda: sarebbe potuto succedere in Java? Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori • Molto potenti... – vettori di dimensione determinata dinamicamente – passaggio di parametri per riferimento • in un linguaggio che prevede passaggio solo per copia – possibilità di scrivere codici più efficienti – controllo diretto delle risorse, a basso livello – strutture dati flessibili Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori • Molto potenti... "Ad un grande potere corrisponde una grande responsabilità." – lo zio di Spiderman Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • memory leak (“falla di memoria”) int una_funzione () { int *un_puntatore; /* alloco un vettore di 100 interi */ un_puntatore = (int*)calloc( 100, sizeof(int)); /* uso il vettore */ ... /* fine della funzione */ return 0; } Manca la deallocazione! ( free(un_puntatore); ) All'uscita della funzione il puntatore "un_puntatore" è perso per sempre, e con lui la possibilità di liberare ("sprenotare", per così dire) la memoria. Ogni volta che si accede a questa funzione, si perdono (leak) 100x4 bytes di memoria Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • un altro caso di memory leak ... int *un_puntatore; /* alloco un vettore di 100 interi */ un_puntatore = (int*)calloc( 100, sizeof(int)); /* uso il vettore */ ... /* rialloco un altro vettore */ un_puntatore = (int*)calloc( 100, sizeof(int)); Manca la deallocazione! ( free(un_puntatore); ) Anche qui, il puntatore "un_puntatore" è perso per sempre, e con lui la possibilità di liberare ("sprenotare", per così dire) la memoria. Ogni volta che si accede a questa funzione, si perdono (leak) 100x4 bytes di memoria Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • un altro caso di memory leak ... int *un_puntatore, i; /* alloco un vettore di 100 interi */ un_puntatore = (int*)calloc( 100, sizeof(int)); /* uso il vettore */ ... /* rialloco un altro vettore */ un_puntatore = &i; Manca la deallocazione! ( free(un_puntatore); ) Anche qui, il puntatore "un_puntatore" è perso per sempre, e con lui la possibilità di liberare ("sprenotare", per così dire) la memoria. Ogni volta che si accede a questa funzione, si perdono (leak) 100x4 bytes di memoria Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • stale pointer (“puntatore andato a male”) /* funzione che restituisce un puntatore ad un intero */ int* una_funzione () { int *punt; int x=10; ... return &x; /* restituisci il puntatore che punta alla variabile x */ } la variabile x non sopravvive al termine della funzione! l'indirizzo di memoria &x non è più valido allora! Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • dereferenced NULL int *punt = NULL; * punt = 10; Errore, ma nessun disastro, il sistema se ne accorge in run time (hopefully)... L’esecuzione terimina (con un segmentation fault) Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • dangling pointers (puntatori penzolanti) int *punt ; * punt = 10; chissà in che locazione verrà scritto quel dieci... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • overrun screw (indicizzare oltre i boundaries) int *punt = (int*) calloc(5,sizeof(int)); punt[5] = 10; chissà in che locazione verrà scritto quel dieci... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • overrun screw (indicizzare oltre i boundaries) int punt[ 5 ]; punt[5] = 10; chissà in che locazione verrà scritto quel dieci... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • fandango on core (andare con un puntatore oltre i boundaries) int *punt = (int*) malloc(sizeof(int)); * punt[5] punt ++; = 10; * punt = 10; chissà in che locazione verrà scritto quel dieci... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • uso dopo deallocazione int *punt = (int*) calloc(10,sizeof(int)); ... free(punt); * punt = 10; chissà in che locazione verrà scritto quel dieci... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • altro errore comune ... /* funzione che restituisce un puntatore ad un intero */ int* una_funzione () { int x; x=10; ... free( &x ); /* libera la memoria usata da x (?) */ } le variabili allocate staticamente (in maniera automatica) vengono anche disallocate automaticamente alla fine del blocco! regola d’oro: free va usato solo con i puntatori restituiti da malloc / calloc Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Puntatori: pasticci • altro errore comune : aliasing bug ... int *x, *y; /* alloco px */ x= (int*) malloc(sizeof(int)); /* assegno y = x. Ora x e y puntano allo stesso blocco di memoria */ y = x; /* uso x */ ... /* libero x */ free( x ); /* uso y */ *y = 10; medicina: meglio usare un solo puntatore per ogni blocco di memoria allocato Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Ripasso costrutti base: Istruzioni di Controllo del Flusso nozioni di sintassi e semantica (intuitivamente, non formalmente) Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria if then else • costrutto condizionale if (<expression>) <statement1> else <statement2> Come gia’ detto, esegue statement1 (il ramo then) sse l’espressione risulta diversa da zero Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria <statement> • Esempi di <statement>s: y = x + 10; nota: punto e virgola... { y = x + 10; z = 4; }; niente punto-e-virgola! Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria if then else • costrutto condizionale if (<expression>) <statement1> else <statement2> if (x) y = x + 10; else y = 20; if (x==2) {y = x + 10; ... } else y = 20; Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria Lo sapevate che... • In C, quasi tutti gli statement sono anche espressioni? • Ad esempio, l’assegnamento x = y e’ anche un’espressione, che vale il valore assegnato (e ha anche il suo tipo) • Cio’ consente di scrivere, per esempio: int x,y,z; x = y = z = 10 ; (non solo e’ coinciso, ma e’ anche efficiente, come da filosofia C) Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria if then else: trappole • errore di sintassi (non compila, innocuo) if (x==2) {y = x + 10; ... }; else y = 20; • errore nella guardia (compila: errore “cattivo”. Cosa fa?) if (x=2) { y = x + 10; ... }; • punto-e-virgola di troppo (compila: errore “cattivo”. Cosa fa?) if (x==2); { y = x + 10; ... }; Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria for • costrutto iterativo for (<expr0>;<expr1>;<expr2>) <stat> for (i=0,j=10;(j>20) &&(i<5); i++, j--) { vect[i]+=10; printf(“%d”, vect[i]); } Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria while • ciclo while while (<expr0>) <stat> while (i<N && a[i]< 1000) i = i + 1; Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria do while • ciclo do-while do <stat> while (<expr0>) do { printf("Immettere un valore intero pari\n"); scanf("%d",&a); /* leggi il numero a da tastiera */ } while(a%2); Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria switch • costrutto condizionale a più vie switch (<expr0>) { case <const1>: <stat1> break; ... case <const2>: <stat2> break; } switch (ch){ case 'a': case 'e': case 'i': case 'o': case 'u': default : } cont_a++; break; cont_e++; break; cont_i++; break; cont_o++; break; cont_u++; break; cont_car++; Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria switch • senza break: fall trought switch (oggi){ case LUN: ... /* gestisci il caso LUN */ break; case MAR: ... /* gestisci il caso MAR */ break; case SAB: ... /* operazioni solo per il SAB */ /* FALL TROUGHT */ case DOM: ... /* gestisci per il SAB e la DOM */ break; default : ... /* gestisci gli altri casi */ } Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria labels e goto • salti non strutturati – di solito, simbolo di cattiva programmazione • (programmi spaghetti) – perlomeno, non eleganti <label>: goto <label>; Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria labels e goto • ad esempio: i=0; while (i <= NUM) printf("%d \n",++i); ... • equivalente a: i=0; INIZIO : if (i>NUM) goto FINE; printf("%d \n",++i); goto INIZIO; FINE : ... Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria break e continue • utilizzabili in tutti i cicli – for, while, do-while • break = esci dal ciclo – (vai alla prima iterazione dopo il ciclo) • continue = interrompi l’iterazone corrente – vai all’inizio della prossima iterazione – (dove, per prima cosa, la guardia di uscita dal ciclo viene testata) Marco Tarini ‧ Laboratorio di Linguaggi ‧ 2004/05 ‧ Università dell’Insubria