Il compilatore C

Nota

Questa guida è una traduzione parziale di Unix Programming Tools, una guida scritta per il corso CS107 presso la Stanford University.

Solitamente i sistemi operativi mettono a disposizione il comando cc (che starebbe per C compiler) per compilare i programmi in C, questo comando è in realtà un alias che si riferisce al compilatore C installato sul sistema, solitamente gcc (GNU C Compiler) o clang (C Language Compiler).

In questa sezione viene presentato il compilatore gcc, un prodotto del progetto GNU open source. L’uso di gcc presenta diversi vantaggi: tende ad essere abbastanza aggiornato e affidabile, è disponibile su una varietà di piattaforme e, ovviamente, è gratuito e open source. Gcc può compilare C, C++ e Objective-C. Gcc in realtà è sia un compilatore che un linker. Ciò vuol dire che una singola chiamata a gcc eseguirà l’intera operazione di linking e di compilazione. Ad esempio, per piccoli progetti potresti utilizzare un comando come il seguente che compila e collega insieme tre file .c per creare un eseguibile chiamato “program”:

gcc main.c module1.c module2.c -o program

La riga precedente potrebbe essere riscritta in modo equivalente per separare i tre passaggi di compilazione dei file .c seguiti da un passaggio di collegamento per creare il programma:

gcc -c main.c     # compila il file .c in file oggetto (.o)
gcc -c module1.c  # compila il file .c in file oggetto (.o)
gcc -c module2.c  # compila il file .c in file oggetto (.o)
gcc main.o module1.o module2.o -o program ## Esegue il linking dei file oggetto

La forma generale per invocare il comando gcc è:

gcc option(s) file(s)

dove options è una lista di flag che dicono a gcc come effettuare la compilazione e files è una lista di file che verranno processati da gcc.

Opzioni del compilatore

Come la maggior parte dei programmi Unix, gcc supporta molte opzioni della riga di comando per controllarne il funzionamento. Sono tutti documentati nella sua pagina man. Possiamo tranquillamente ignorare la maggior parte di queste opzioni e concentrarci su quelle più comunemente usate: -c, -o, -g e -Wall.

Opzione Descrizione
-c files compila i file sorgente in file oggetto senza passare attraverso la fase di collegamento. I Makefile (sotto) usano questa opzione per compilare i file uno alla volta.
-o file Specifica che l’output di gcc dovrebbe essere denominato file. Se questa opzione non è specificata, il nome predefinito utilizzato dipende dal contesto: (a) se si compila un file sorgente .c, il file oggetto di output verrà nominato con lo stesso nome ma con estensione .o. In alternativa, (b) se si effettua il collegamento per creare un eseguibile, il file di output verrà denominato a.out. Molto spesso, l’opzione -o viene utilizzata per specificare il nome del file di output quando si collega un eseguibile, mentre per la compilazione, le persone lasciano semplicemente che prenda il sopravvento la denominazione predefinita .c/.o.
-g Indica al compilatore di includere informazioni di debug aggiuntive nel proprio output. Ti consiglio di compilare sempre il tuo codice sorgente con questa opzione, in modo da poter usare il debugger.
-Wall Fornisce avvisi su possibili errori nel codice sorgente. I problemi rilevati da -Wall non sono esattamente errori, sono costrutti che il compilatore ritiene possano essere errori. Ti consiglio vivamente di compilare il codice con -Wall. Trovare bug in fase di compilazione è davvero molto più semplice che in fase di esecuzione. L’opzione -Wall può sembrare fastidiosa, ma ne vale la pena.