290 likes | 442 Views
Università dell’Insubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2006/07. Laboratorio di Linguaggi lezione II. Marco Tarini. Laboratorio di Linguaggi. docente : Marco Tarini e-mail: tarini@isti.cnr.it
E N D
Università dell’Insubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2006/07 Laboratorio di Linguaggilezione II Marco Tarini
Laboratorio di Linguaggi • docente: Marco Tarini e-mail: tarini@isti.cnr.it • ricevimento: Mercoledì dalle 11:00 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 M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Laboratorio di Linguaggi v= argomanto già trattato • link utile: http://vcg.isti.cnr.it/~tarini/linguaggi/ • guida essensiale di alcuni emementi di C M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Prima di andare avanti • in questi lucidi (e nell'ambiente DevC++) le reserved words sono in blu! • non si possono usare per gli identificatori • ma, ricordiamoci, il C è case sensitive • " " non si è un nome lecito per una nuova var , ma " " si. int potenza (int b, int e) { int res=1 , i; for (i=1; i<=e; i++) { res = res * b; } return res; } int Int M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Un programma completo dichiaria che verranno usate due librerie standard: “standard Input Output” e “Standard Library” printf = scrivi sullo STANDARD OUTPUT (esempio di funzione che NON fa parte del core del lingauggio, è definito in stdio.h) • il cosidetto "hello world" #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { printf("Ciao Mondo!\n"); return 0; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Compilazione (o "build", o "make") ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sorgente binario file “main.c“ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { printf("Ciao Mondo!\n"); return 0; } COMPILAZIONE main.exe ESEGUZIONE C:\> main.exe C:\> Ciao Mondo! C:\> M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Risassumendo • Compilazione (build, make)(TRE FASI) • Precompliazione • (di ogni file sorgente ".c") • (utilizzando anche i file headers ".h") • Compilazione (vera e propria) • (per ogni file sorgente ".c" risultante) • Linking • (di tutti i ".o" risultanti insieme) • (utilizzando anche i file di libreria) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore • #= istruzione per il preprocessore: • ≪d'ora in poi, quando scrivo LIMIT, fai finta che abbia scritto 10≫ • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT 10 int main() { ... if (x < LIMIT) { ... ... } else { ... ... } ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore int main() { ... if (x < 10) { ... ... } else { ... ... } ... } precompliler • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT 10 int main() { ... if (x < LIMIT) { ... ... } else { ... ... } ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore int main() { ... if (x < 10) { ... ... } else { ... ... } ... } precompliler • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT x int main() { ... if (LIMIT < 10) { ... ... } else { ... ... } ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore int fattoriale(int a) { int res=1; printf("valore di a:%d \n",a); while (a>1) { res*= (a--); } return res; } precompliler • Costrutti condizionali • statici, fatti prima del compilatore! #define DEBUG 1 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore int fattoriale(int a) { int res=1; while (a>1) { res*= (a--); } return res; } precompliler • Costrutti condizionali • statici, fatti prima del compilatore! #define DEBUG 0 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore la guardia viene controllata solo durante la compilazione risultato: programma efficiente! la guardia viene controllata durante ogni esecuzione! risultato: programma inefficiente! • Costrutti condizionali statici • perchè é una tale furbata? #define DEBUG 0 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } int DEBUG = 0; int fattoriale(int a) { int res=1; if (DEBUG) { printf("valore di a:%d \n",a); } while (a>1) { res*= (a--); } return res; } VS. M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore • si possono anche usare #ifndef DEBUG #undef DEBUG #if defined (DEBUG) • Costrutti condizionali statici • due forme sintattiche equivalenti #define DEBUG 1 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } #define DEBUG int fattoriale(int a) { int res=1; #ifdef DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Precompilatore questo tipo di flags (SUN, HP9000...) sono definite nell’ambiente. Il compilatore lo sa. Non vanno specificate a mano nel codice • Costrutti condizionali statici • altro tipico uso: • specializzazione del codice per architetture specifiche • (remember: niente macchine virtuali in C) ... #if defined (HP9000) || defined(SUN) /* codice funzionante SOLO per le sun o per le HP9000 */ ... #else /* codice buono per le altre architettutre */ ... #endif ... M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
L’ultima fatica del Precompilatore Inclusione file di header file “cambi.h“ const int LIRE_PER_EURO = 1955; file “main.c“ const int LIRE_PER_EURO = 1955; int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } #include "cambi.h" int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } precompliler M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
L’ultima fatica del Precompilatore Inclusione file di header file “cambi.h“ const int LIRE_PER_EURO = 1955; pernacchia :P prrrrrr $£!@&& const int LIRE_PER_EURO = 1955; pernacchia :P prrrrrr $£!@&& int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } file “main.c“ #include "cambi.h" int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } precompliler pura, meccanica, manipolazione sintattica ! M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa è successo esattamente quando "compliamo" il progetto? (quasi) linguaggio macchia in C ancora in C Source File "main.c" file precomp. object file "main.o" precompiler compiler M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Compilazione (o "build", o "make") sorgenti binario file “main.c“ COMPILAZIONE ("BUILD")("MAKE") [ codice in C ] main.exe file “main.h“ [ altro codice ] M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Compilazione (build) sorgenti binario file “main.c“ COMPILAZIONE ("BUILD")("MAKE") [ codice in C ] main.exe file “main.h“ [ altro codice ] file “zap.c“ [ altro codice ] Progetto con più file sorgenti ! file “pippo.c“ [ altro codice ] M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa è successo esattamente "compliamo" il progetto? file precomp. 1 object file "main.o" pre- complier compiler file precomp. 2 object file "pippo.o" pre- complier compiler eseguibile finale "prova.exe" linker file precomp. 3 object file “pluto.o" pre- complier compiler libreria A libreria B Source File 1 "main.c" Source File 2 "pippo.c" Source File 3 “pluto.c" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Tipi Base esegue b se e solo se x è zero. esegue a in tutti gli altri casi (anche se x è negativo) vale anche per i tipi non interi... • tipi base: • intero • floating point • booleano • tipi derivati: • enumerazione • strutture • arrays int x; ... if (x) a(); else b(); M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Tipi Base : interi minino valore assumibile massimo valore assumibile dimensione (in bytes) tipo 1 2* 4* 4* - 128 +127 - 32K +32K (-1) - 2*K*K*K +2*K*K*K (-1) (idem) (idem) char short int long * Di solito. Dipende dalla macchina. (remember: niente macchine astratte!) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Tipi Base : interi Variante unsigned Esempio: unsigned int pippo; con questa variante, si risparmia il bit del segno. minino valore assumibile massimo valore assumibile dimensione (in bytes) tipo 1 2* 4* 4* 0 0 0 0 +255 +64K (-1) +4*K*K*K (-1) (idem) char short int long * Di solito. Dipende dalla macchina. (remember: niente macchine astratte!) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Definiamo un nuovo tipo typedef unsigned char Byte; typedef unsigned char Byte; typedef <descrizione del tipo> <identificatore del tipo>; Byte a,b,c; int main(){ Byte pippo=21, panco; ... } (ricordiamoci la filosofia del C: linguaggio scarno, ma estendibile!) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Literals interi • Molti modi per scriverle… const int PIPPO = 12; int a,c = 16, b; int main(){ char pippo= 67; if (pippo + a > 21) { ... } else { b = 4; ... } } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Literals interi codifica base 16: 0123456789ABCDEF 0xFFFF 0xA000 0xFFFFFFFFFF codifica ASCII (per caratteri). 'A' =65 'B' =66 'a' =97 'b' =98 '+' =43 '?' =67 etc. (256 "caratteri" in tutto) codifica base 8: 01234567 013 0100 • Molti modi per scriverle… const int PIPPO = 12; int a,c = 0x10, b; int main(){ char pippo= 'C'; if (pippo + a > 025) { ... } else { b = 4; ... } } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Piccoli trucchi con i chars • Caratteri ASCII e numeri di un byte sono proprio lo stesso tipo! char c0, c1; ... if (c0<c1) { /* c0 viene prima di c1 in ordine alfabetico */ ... } else { /* c0 viene dopo di c1 in ordine alfabetico, o c0==c1 */ ... } (ricordiamoci la filosofia del C: linguaggio che permette di dire tutto in poche righe di codice.) (poche e quindi talvolta criptiche. Usare commenti!) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Piccoli trucchi con i chars • Caratteri ASCII e numeri di un byte sono proprio lo stesso tipo! /* restituisce 1 se il carattere e' una lettera minuscola, o 0 altrimenti */ intis_minuscolo(char c){ if ( (c>=‘a') && (c<=‘z') ) return 1; return 0; } /* restituisce la versione minuscola di un carattere dato*/ char minuscolo(char c){ if ( (c>='A') && (c<='Z') ) returnc-'A'+'a'; elsereturnc; } (ricordiamoci la filosofia del C: linguaggio che permette di dire tutto in poche righe di codice.) (poche e quindi talvolta criptiche. Usare commenti!) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 6 / 0 7 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a