Laboratorio di Linguaggi lezione IX: Dentro le Librerie Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2004/05
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Esercizio Non esiste il tipo bool Come si puo fare ad aggiungerlo? –in modo che sia possibile scrivere, per esempio: Bool b; int x; int main(){ b = ( x == 0); if (b) {... } b = !b; } Bool b0,b1,b2 = TRUE; int main(){... b0 = b1 && b2; while (b0) {... }
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Esercizio: alcune soluzioni soluzione 1: soluzione 2: soluzione 3: typedef enum {FALSE, TRUE} Bool; typedef int Bool; const Bool TRUE = 1; const Bool FALSE = 0; #define Bool int #define TRUE 1 #define FALSE 0 Bool b; int x; int main(){ b = ( x == 0); if (b) {... } b = !b; } Bool b0,b1,b2 = TRUE; int main(){... b0 = b1 && b2; while (b0) {... }
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file "bool.h" E' gia' una micro-libreria ! typedef enum {FALSE, TRUE} Bool; Bool b; int x; int main(){ b = ( x == 0); if (b) {... } b = !b; } Bool b0,b1,b2 = TRUE; int main(){... b0 = b1 && b2; while (b0) {... } #include "bool.h"
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Inclusione files #include "bool.h" Due sintassi diverse per "includere" un file #include "inserisci un file che fa parte di questo progetto" (il file verrà cercato nella directory corrente) "inserisci una una libreria esterna" (il file verrà cercato nelle apposite "directories 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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Inclusione files
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Diamo una occhiata
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Definizioni e dichiarazioni int potenza (int b, int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } tipo del risultato: intero (output della funzione) lista dei parametri formali, ciascuno preceduto dal tipo (input della funzione) corpo della funzione cosa fa un blocco delimitato da {} comando return: restituzione del risultato, e uscita dalla funzione ci deve essere! variabili locali qui, due visibili solo nel corpo della funzione. dichiarate allinizio! nome (identificatore) della funzione: potenza
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Definizioni e dichiarazioni int potenza (int b, int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } int potenza (int b, int e); dichiarazione della funzione o prototipo della funzione - "tutto quello che serve sapere per usare la funzione (a scatola chiusa)" definizione della funzione o implementazione della funzione - "le istruzioni dettagliate per eseguire la funzione"
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Definizioni e dichiarazioni Esempio int potenza (int b, int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } int main(){ int x; x = potenza(5, 6); }
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Definizioni e dichiarazioni Esempio: invertiamo l'ordine per capriccio int main(){ int x; x = potenza(5, 6); } int potenza (int b, int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } errore in compilazione: identificatore sconosciuto: "potenza"
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Definizioni e dichiarazioni Esempio int potenza (int b, int e ); int main(){ int x; x = potenza(5, 6); } int potenza (int b, int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } (i nomi dei parametri formali si possono anche omettere)
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " main.c " file " potenze.c " Progetti a piu' files Schema #include "potenze.h" int main(){ int x; x = potenza(5, 6); } int potenza(int b,int e) { int res=1, i; for (i=1; i<=e; i++) { res = res * b; } return res; } file " potenze.h " int potenza(int b,int e); #include "potenze.h"
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Struttura della compilazione main.c potenze.c potenze.h pre- process. file precomp. 1 compiler object file main.o pre- process. file precomp. 3 compiler object file potenze.o eseguibile finale exec.exe linker
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Con DevC++ Tasto destro sul progetto
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Con DevC++
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Con DevC++
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Con DevC++ Ripentendo per potenza.h si ottiene: nota: "compile" VS "build" (anche: "make")
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " main.c " file " auxiliary.c " Progetti a piu' files: schema base #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } #include "auxiliary.h" int funz1(int b,int e) {... /* corpo di funz1 */ } void funz2(double*) {... /* corpo di funz1 */ } file " auxiliary.h " int funz1(int,int); void funz2(double*);
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int funz1(int b,int e) {... /* commento implementativo */... } void funz2(double*) {... } file " main.c " Ricordarsi di commentare! #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* funzione 2: blah blah */ void funz2(double*); commenti ad alto livello! (su cosa fanno -in totale- e come si usano le funzioni)
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int funz1(int b,int e) {... /* corpo di funz1 */ } void funz2(double*) {... /* corpo di funz1 */ } file " main.c " Progetti a piu' files: esempio di errore #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " int funz1(int,int); void funz2(double*);...niente funz 2
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files: esempio di errore eseguibile finale exec.exe linker main.c auxiliary.c auxiliary.h pre- process. file precomp. 1 compiler object file main.o pre- process. file precomp. 3 compiler object file auxiliary.o
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a
file " auxiliary.c " #include "auxiliary.h" void funz_pippo(int x) {... } int funz1(int b,int e) {... funz_pippo( b + 1);... } void funz2(double*) {... } file " main.c " Funzioni "interne" #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " int funz1(int,int); void funz2(double*); void funz_pippo(int x) {... } la funzione "funz_pippo" non e' dichiarata nell'header. Sarà visibile al compilatore solo nel file in cui viene definita.
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" void funz_pippo(int x) {... } int funz1(int b,int e) {... funz_pippo( b + 1);... } void funz2(double*) {... } file " main.c " Progetti a piu' files: collisioni #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " int funz1(int,int); void funz2(double*); void funz_pippo(int x) {... } int funz_pippo() {... }
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files: collisioni eseguibile finale exec.exe linker main.c auxiliary.c auxiliary.h pre- process. file precomp. 1 compiler object file main.o pre- process. file precomp. 3 compiler object file auxiliary.o linker funz_pippo
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a
file " auxiliary.c " #include "auxiliary.h" void funz_pippo(int x) {... } int funz1(int b,int e) {... funz_pippo( b + 1);... } void funz2(double*) {... } file " main.c " Progetti a piu' files: funzioni "interne" #include "auxiliary.h" double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " int funz1(int,int); void funz2(double*); void funz_pippo(int x) {... } int funz_pippo() {... }
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" void funz_pippo(int x) {... } int funz1(int b,int e) {... funz_pippo( b + 1);... } void funz2(double*) {... } file " main.c " Progetti a piu' files: funzioni "interne" #include "auxiliary.h"... double d; int main(){ int x;... x = funz1(5, 6);... funz2( &d );... } file " auxiliary.h " int funz1(int,int); void funz2(double*); static void funz_pippo(int x) {... } la funzione "funz_pippo" ora non è visibile (all'esterno) nemmeno dal linker ! morale della favola: le funzioni "interne" meglio dichiararle static
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files Condivisione di... –funzioni –variabili –costanti –macros –tipi di dato
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: condivisione variabili #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); int pippo = 2; collisione! multiple definition of variable "pippo"
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: condivisione variabili #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); extern int pippo; extern
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files: condivisione variabili definizione di una var: 1.alloca dello spazio di memoria per un nuovo intero 2.(opzionale) inizializza: scrivi "3" in quello spazio 3.d'ora in poi, pippo si riferira' a quello spazio extern int pippo; int pippo = 3; dichiarazione di una var: 1."prometto che da qualche parte sara' definita una variabile che si chiama pippo, e sara' un intero" 2. pippo si riferira' allo spazio di quella variabile
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: condivisione variabili #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo; al solito, i commenti di spiegazione...
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; int i=0; int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: variabili "interne" #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " la variabile " i " non e' dichiarata nell'header. Sarà visibile (al compilatore) solo nel file in cui viene definita. /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo;
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; int i=0; int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: variabili "interne" #include "auxiliary.h" int i=0; int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo; collisione! multiple definition of variable " i " solito probelma...
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; static int i=0; int funz1(int b,int e) { pippo = 16;... } file " main.c " Progetti a piu' files: variabili "interne" #include "auxiliary.h" int i=0; int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo; solita soluzione: Dichiarare static le variabili "interne".
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a I due significati diversi di 1.se riferito a var locali : "variabili che hanno lo scope di var. locali ma sono per tutto il resto var. globali" (vedi lez. 8) 2.se riferito a var globali : "variabili non visibili all'esterno del source corrente, neanche dal linker (= vars che il linker deve ignorare)" static o funzioni...
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files Condivisione di... –funzioni –variabili –costanti –macros –tipi di dato
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; static int i=0; int funz1(int b,int e) {... pippo... } file " main.c " Progetti a piu' files: condividere costanti #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo; /* MAXN: il numero max... blah blah */ const MAXN = 100;
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; static int i=0; int funz1(int b,int e) {... pippo... } file " main.c " Progetti a piu' files: condividere macro #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* funzione 1: blah blah */ int funz1(int,int); /* pippo: blah blah */ extern int pippo; /* MAXN: il numero max... blah blah */ #define MAXN 100
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " auxiliary.c " #include "auxiliary.h" int pippo=2; static int i=0; int funz1(int b,int e) {... pippo... } file " main.c " Progetti a piu' files: condividere macro #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " auxiliary.h " /* MAXN: il numero max... blah blah */ #define MAXN 100 typedef enum {... } TipoStrano; /* funzione 1: blah blah */ int funz1(int, int); /* pippo: blah blah */ extern int pippo;
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a file " TipoStrano.c " #include "auxiliary.h" int pippo=2; static int i=0; int funz1(int b,int e) {... pippo... } file " main.c " Progetti a piu' files: condividere macro #include "auxiliary.h" int main(){ int x; x = funz1(5, 6);... if (pippo)...;... } file " TipoStrano.h " /* MAXN: il numero max... blah blah */ #define MAXN 100 typedef enum {... } TipoStrano; /* funzione 1: blah blah */ int funz1(TipoStrano,int); /* pippo: blah blah */ extern int pippo;
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files Condivisione di... –funzioni –variabili –costanti –macros –tipi di dato
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files: perchè? Scopi: –Modularità del progetto software dividere il progetto in aree concettualmente separate mantenibilita', chiarezza... –Separazione interfaccia / implementazione –Riutilizzabilità del codice –Parallelizzazione dello sviluppo software –Riduzione tempo di ri-compilazione (sempre meno) (ma, storicamente, tra le motivazioni principali)
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Le librerie esterne #include NB: parentesi angolate
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Librerie standard più comunemente usate... : Utilità generali (malloc, calloc, free, NULL, rand...) : Input/Output (printf, sprintf, scanf, FILE...) : Funzioni matematiche (sin, cos, exp, sqrt, fabs...) : Funzioni su caratteri (isdigit, isgraph...) : Funzioni su stringhe (strcmp, strcpy) : Funzioni di ora e data (clock, time...) : Definizioni valori Limite di interi (INT_MAX, INT_MIN...) : Definizioni valori Limite di floats (DBL_MAX, DBL_MIN...) : Diagnostica (assert)
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Uso di librerie e linker Esempio: la libreria OpenGL (grafica 3D) #include... int main(){... /* usa OpenGl */... } Sono dichiarazioni ("promesse"). E le definizioni corrispondenti? Il file GL/gl.h contiene: – definizioni tipi di dato – funzioni (i prototipi) – variabili (come "extern") – costanti – macros
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Progetti a piu' files: inclusione di librerie eseguibile finale exec.exe linker main.c sorgenti di OpenGL OpenGL.h pre- process. file precomp. 1 compiler object file main.o pre- process. file precomp. 3 compiler file di libreria (già compilata) OpenGL32.lib
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 / 0 5 U n i v e r s i t à d e l l I n s u b r i a Per linkare la libreria (già compilata) in Dev-C++