220 likes | 405 Views
Compilazione di Programmi C/C++. Cominciamo col mostrare i passi principali da compiere per compilare i vostri programmi C (o C++). Poi procederemo a descrivere formalmente il modello di compilazione C e come il C supporta librerie addizionali. Creare, Compilare e Eseguire il Vostro Programma.
E N D
Compilazione di Programmi C/C++ • Cominciamo col mostrare i passi principali da compiere per compilare i vostri programmi C (o C++). • Poi procederemo a descrivere formalmente il modello di compilazione C e come il C supporta librerie addizionali.
Creare, Compilare e Eseguire il Vostro Programma Creare il programma • Create un file contenete il programma completo. Per creare il file potete usare ogni editor ordinario con il quale abbiate familiarità (vi, kedit, nedit). • Il nome di file deve per convenzione terminare con “.c‘”, e.g. myprog.c o progtest.c. I contenuti devono essere conformi alla sintassi C.
Compilazione • Ci sono molti compilatori C disponibili. cc è il compilatore di default nei sistemi Unix. Il compilatore GNU C gcc è popolare e disponibile per molte piattaforme. Gli utenti di PC potrebbero essere familiari col compilatore Borland bcc. • Ci sono anche compilatori equivalenti C++ che di solito si chiamano CC (notate il maiuscolo). Per esempio, CC e GNU GCC. Il compilatore GNU si chiama anche g++ . • Esistono altri compilatori C/C++ (meno comuni). Tutti i compilatori citati sopra operano essenzialmente nello stesso modo e hanno molte opzioni command line in comune.
Compilazione • la migliore fonte di informazioni su ogni compilatore è il suo manuale in linea: e.g. man cc. • per compilare in vostro programma semplicemente invocate il comando cc. Il comando deve essere seguito dal nome del programma (C) che volete compilare. E’ possibile specificare anche alcune opzioni di compilazione. Quindi il comando di compilazione di base è: cc program.c dove program.c è il nome del file.
Compilazione • Se ci sono errori ovvi nel programma (di battitura, scrittura sbagliata di una delle key words o omissione di un punto e virgola), il compilatore li troverà e li riporterà. • Ci possono essere ovviamente errori logici che il compilatore non può scoprire. Potreste stare chiedendo al computer di fare operazioni sbagliate. • Quando il compilatore ha “digerito” con successo il vostro programma, la versione compilata (eseguibile) è lasciata in un file chiamato a.out o, se viene usata l’opzione -o, nel file citato dopo il o.
Compilazione E’ più conveniente usare un -o e il nome del file nella compilazione come in cc -o program program.c che mette il programma compilato nel file program (o in un qualsiasi file citato nel nome che segue l’argomento “-o”) invece di metterlo nel file a.out .
Eseguire il programma • Il passo successivo è di eseguire il programma compilato. Per lanciare un eseguibile in UNIX, basta semplicemente digitare il nome del file che lo contiene, in questo caso program (o a.out), preceduto dalla working directory corrente (./program, ./a.out). • Questo manda in esecuzione il programma, stampando i risultati sullo schermo. A questo punto ci possono essere errori run-time, come divisioni per zero, o può divenire evidente che il programma ha prodotto un output non corretto. • In tal caso, occorre editare il sorgente del programma, ricompilarlo e eseguirlo di nuovo.
Il Preprocessore Il Preprocessore accetta codice sorgente in ingresso e ha la responsabilità di • rimuovere i commenti • interpretare preprocessor directives indicate dal #. Per esempio #include – include i contenuti del file nominato. I file inclusi sono tipicamente header files. #include <math.h> -- standard library maths file. #include <stdio.h> -- standard library I/O file. #define – definisce un nome simbolico o costante. Macro substitution. #define MAX_ARRAY_SIZE 100
Compilatore C Il compilatore C traduce codice sorgente in codice assembly. Il codice sorgente è quello prodotto dal preprocessore.
Assembler L’assembler crea codice oggetto. In un sistema UNIX si possono vedere file con un suffisso .o (.OBJ in MSDOS/WIN) che indica file di codice oggetto.
Link Editor Se un file sorgente fa riferimento a funzioni di libreria o a funzioni definite in altri file sorgente il link editor combina queste funzioni (col main()) per creare un file eseguibile. Anche i riferimenti a variabili esterne sono risolti in questa fase.
Alcune Opzioni del Compilatore -c Sopprime il processo di linking e produce un file .o per ogni file sorgente listato. Questi possono essere successivamente linkati sempre col comando cc: cc file1.o file2.o ...... -o executable -llibrary Linkare con librerie oggetto. Questa opzione deve seguire gli argomenti di tipo file sorgente. Le librerie oggetto sono archiviate e possono essere standard, di terze parti o create dall’utente. Probabilmente la libreria più usata è la math library (libm.a). Occorre linkare questa libreria esplicitamente se si vogliono usare le funzioni matematiche (non dimenticare anche di #include l’header file <math.h> ), ad esempio: cc calc.c -o calc -lm
Alcune Opzioni del Compilatore -Ldirectory Aggiunge directory alla lista di directory contenente object-library routines. Il linker cerca sempre le librerie standard e di sistema in /lib and /usr/lib. Se si vogliono linkare librerie che sono state create o installate dall’utente (a meno che questi non abbia i privilegi necessari ad installare le librerie in /usr/lib) è necessario specificare la directory dove i file sono memorizzati, ad esempio: cc prog.c -L/home/myname/mylibs mylib.a
Alcune Opzioni del Compilatore -Ipathname Aggiunge pathname alla lista di directory in cui cercare #include files con filename relativi (che non cominciano con slash /). Per default, il preprocessore prima cerca #include files nella directory contenente il file sorgente, poi nelle in directories indicate con le opzioni -I options (se presenti), e finalmente, in /usr/include. Quindi per includere header files memorizzati in /home/myname/myheaders occorre: cc prog.c -I/home/myname/myheaders Nota: I system library header files sono memorizzati in una posizione speciale (/usr/include) e non sono influenzati dall’uso dell’opzione -I. System header files e user header files vengono trattati in maniera lievemente differente.
Some Useful Compiler Options -g invoca l’opzione di debugging. Questa dice al compilatore di produrre informazioni addizionali sulla tabella dei simboli che vengono usate da una varietà di tool di debugging. -D definisce simboli o come identificatori (-Didentifer) o come valori (-Dsymbol=value) in una maniera del tutto simile al comando del preprocessore #define .
Uso delle Librerie Il C è un linguaggio estremamente piccolo: molte delle funzioni disponibili in altri linguaggi non sono presenti in C (e.g. niente I/O, funzioni per gestione stringhe o matematiche). A che serve il C allora? Il C fornisce funzionalità mediante un ricco insieme di librerie di funzioni. Come risultato la maggior parte delle implementazioni C includono librerie standard di funzioni per molte funzionalità ( I/O etc.). Dal punto di vista pratico queste possono essere considerate come facenti parte del C. Ma possono variare da macchina a macchina (Borland C vs. UNIX C).
Uso delle Librerie Il programmatore può anche sviluppare le sue librerie di funzioni o anche usare librerie di terze parti special purpose (e.g. NAG, PHIGS). Tutte le librerie (eccetto quelle di standard I/O) devono essere esplicitamente linkate con le opzioni del compilatore -l e, possibilmente, -L, descritte prima.
Librerie di Funzioni UNIX Il sistema UNIX dispone di un ampio numero di funzioni di libreria C. Alcune di queste implementano operazioni usate di frequente, mentre altre sono di utilizzo specialistico. Non Reinventare la Ruota: E’ saggio per il programmatore vedere se esiste una funzione di libreria che esegua un certo compito prima di scriverne una propria versione. Questo riduce il tempo di sviluppo del programma. Le funzioni di libreria sono state testate, quindi è più probabile che siano corrette rispetto a qualsiasi funzione che possa essere scritta per l’occasione. Questo riduce anche i tempi di debugging del programma.
Trovare Informazioni sulle Funzioni di Libreria Il manuale UNIX ha un entry per ciascuna funzione disponibile. La documentazione delle funzioni è memorizzata nella sezione 3 del manuale, e molte utili system calls sono contenute nella sezione 2. Se conoscete già il nome della funzione cercata, si può leggere la pagina digitando (ad es., per sqrt): man 3 sqrt Se non conoscete il nome della funzione, una lista completa e’ inclusa nella pagina introduttiva della sezione 3 del manuale. Per leggerla, digitate man 3 intro
Trovare Informazioni sulle Funzioni di Libreria Ci sono circa 700 funzioni descritte qui. Questo numero tende a crescere ad ogni upgrade del sistema. Su ogni pagina del manuale, la sezione SYNOPSIS include informazioni sull’uso della funzione. E.g.: #include <time.h> char *ctime(time_t *clock) Questo significa che occorre includere #include <time.h> nel file sorgente prima di chiamare ctime. E che la funzione ctime ha un puntatore al tipo time_t come argomento, e ritorna una stringa (char *). time_t probabilmente viene definita nella stessa pagina del manuale.
Trovare Informazioni sulle Funzioni di Libreria La sezione DESCRIPTION dà poi una breve descrizione di quello che fa la funzione. Per esempio: ctime() converte un long integer, puntato da clock, in una stringa di 26 caratteri del tipo prodotto da asctime().