2 Livello 0
In questo capitolo muoveremo i primi passi essenziali, sia pratici che teorici, dalla configurazione dell’ambiente di sviluppo alla comprensione del ciclo di compilazione, fino alla scrittura e all’analisi riga per riga del tuo primo programma.
2.1 Configurare l’ambiente di sviluppo
Tutto ciò di cui hai bisogno per iniziare è configurare il tuo ambiente di sviluppo (quello che in gergo chiamiamo IDE). Esistono diverse soluzioni per farlo, e la scelta finale dipenderà in parte dal tuo Sistema Operativo (Windows, macOS o Linux), quindi scegli pure quella che preferisci o con cui ti trovi più a tuo agio.
Ecco le due strade principali che ti consiglio:
CLion (scelta consigliata): come studente di UniCa, puoi richiedere una licenza annuale gratuita (rinnovabile) per tutti i prodotti JetBrains, incluso CLion, uno dei migliori ambienti di sviluppo per il C. Ti basta registrarti con la tua mail istituzionale ed è praticamente pronto all’uso, senza configurazioni complesse. Link per la licenza studenti.
Visual Studio Code (scelta leggera e personalizzabile): la migliore alternativa “leggera” è VS Code. È gratuito, open-source e consuma pochissime risorse. Tieni conto, però, che richiede un minimo di configurazione iniziale in quanto dovrai installare l’estensione per il C/C++ e assicurarti di avere un compilatore (come GCC o Clang) installato sul tuo computer.
Il mio consiglio è di non perdere giorni a cercare l’ambiente di sviluppo “perfetto”. Scegli quello che riesci a installare più facilmente sul tuo computer e inizia a scrivere codice.
Se vuoi capire meglio cosa succede senza delegare nulla a interfacce grafiche complesse, puoi scrivere il codice su un editor di testo (come Notepad++, Sublime Text, o persino il Blocco Note) e usare il terminale (la riga di comando) per compilarlo ed eseguirlo.
2.2 Editor di testo e terminale
In questo ultimo caso ecco come procedere:
- Apri il tuo editor, scrivi il programma e salvalo con l’estensione .c (ad esempio, main.c).
- Apri il terminale e spostati nella cartella in cui hai salvato il file usando il comando cd.
- Digiti il comando per trasformare il testo in un file binario eseguibile.
- Lanci il programma appena generato.
Su macOS: i Mac utilizzano il compilatore clang (che si attiva anche digitando il comando storico gcc). Se il terminale dovesse dirti che il comando non esiste, ti basterà installare il tool a riga di comando digitando xcode-select --install.
Una volta installato, i comandi nel Terminale sono:
gcc -Wall main.c -o il_mio_programmaper compilare./il_mio_programmaper eseguire
Su Windows: puoi usare il prompt dei comandi (CMD). Di base Windows non include un compilatore C. Il modo più pulito per ottenerlo è installare una distribuzione di GCC per Windows (come MinGW-w64, installabile facilmente tramite MSYS2) e assicurarsi di inserire il percorso del compilatore nelle variabili d’ambiente del sistema.
Una volta configurato GCC, i comandi sono del tutto analoghi:
gcc -Wall main.c -o il_mio_programmaper compilareil_mio_programma.exeper eseguire
In Windows, per eseguire il programma, il prefisso .\ è obbligatorio se utilizzi la PowerShell.
Negli esempi di compilazione è presente -Wall (Warning All). Questo comando dice al compilatore di segnalare qualsiasi riga di codice che, pur non bloccando la creazione del programma, risulta potenzialmente problematica.
2.3 Linguaggi di programmazione
Per capire dove si colloca il C, dobbiamo fare un piccolo passo indietro. La storia dell’informatica è legata ad una progressiva astrazione. Esistono tre categorie di linguaggi:
- Linguaggio Macchina: linguaggio che il computer comprende nativamente, è composto esclusivamente da sequenze di bit (0 e 1), tanto elementare per l’hardware quanto impossibile da gestire per un essere umano.
- Linguaggio Assembly: rappresenta il primo livello di astrazione e sostituisce gli 0 e 1 con parole chiave (come ADD o MOV), rendendo il codice leggibile dall’uomo, pur rimanendo legato all’architettura della macchina.
- Linguaggi di Alto Livello: linguaggi vicini alla logica umana e indipendenti dall’hardware. A seconda di come vengono tradotti per la macchina, si dividono in compilati (il codice viene tradotto tutto insieme prima dell’esecuzione) o interpretati (tradotti riga per riga mentre il programma è in esecuzione).
Il C è un linguaggio di alto livello di tipo compilato. Quando scriviamo un programma in C, il nostro testo non può essere eseguito direttamente ma deve attraversare un flusso di lavoro diviso in 6 fasi fondamentali:
- Editing: il programmatore scrive il codice sorgente (es. main.c) utilizzando un editor di testo.
- Preprocessing: il preprocessore analizza il codice sorgente ed esegue tutte le direttive che iniziano con il simbolo
#(come#includee#define), include i file richiesti, effettua le sostituzioni e produce il codice sorgente che verrà effettivamente compilato. - Compilazione: un software chiamato compilatore traduce il codice sorgente in linguaggio macchina, generando il cosiddetto codice oggetto (un file intermedio, non ancora pronto per l’uso).
- Linking: il linker unisce il codice oggetto appena creato con le funzioni delle librerie di sistema. Il risultato di questa unione è il file eseguibile finale (il .exe su Windows).
- Loading: quando lanci il programma, il sistema operativo copia il file eseguibile dal disco fisso alla memoria centrale (RAM) del computer.
- Esecuzione: la CPU legge le istruzioni presenti nella memoria centrale e le esegue una dopo l’altra.
Le ultime due (Loading ed Esecuzione) sono fasi runtime gestite dal Sistema Operativo.
2.4 La struttura di un programma in C
Ora che sei pronto, è arrivato il momento di fare una prova pratica con un programma semplicissimo. Tutto quello che devi fare è aprire un nuovo file nel tuo editor, assegnargli un nome e salvarlo con l’estensione .c.
Riscrivi nel tuo editor il codice che trovi qui sotto:
//Il mio primo programma in C
#include <stdio.h>
int main(void) {
printf("Hello world\n");
return 0;
}A questo punto, non ti resta che compilare ed eseguire il programma. Se tutto è configurato nel modo corretto, il codice girerà senza problemi e non dovresti ricevere alcun tipo di errore o di avviso (warning). Cosa significa questo all’atto pratico? Significa che vedrai comparire la scritta “Hello world” nel terminale (o nella console integrata del tuo IDE).
Questo è il più semplice programma in C che puoi realizzare.
Anche se non hai mai programmato prima penso sia intuitivo capire quanto questo programma in C sia più complesso di quello che potresti scrivere in Python.
# Il mio primo programma in Python
print("Hello world")Prima però di passare a qualcosa di più complesso e decisamente più interessante, fermiamoci un istante a guardare cosa hai appena scritto nel tuo file .c. Sono convinto che comprendere a fondo la struttura di base di un programma in C sia un passo fondamentale per il tuo percorso, ed è molto più facile farlo adesso quando il codice è ancora composto da pochissime righe.
Analizziamolo quindi riga per riga.
I commenti (
//Il mio primo programma in C). Se nel tuo codice inserisci una riga che inizia con due barre oblique (//), stai scrivendo un commento. Questa riga viene completamente ignorata dal compilatore. Tuttavia, usare i commenti all’interno dei tuoi script è fondamentale. Ti consiglio di inserirne il più possibile. Saranno di vitale importanza quando riaprirai il file a distanza di settimane o mesi per capire cosa avevi in mente. Oltre ai commenti su singola riga esiste una seconda forma, utile quando il testo si estende su più righe (tutto ciò che è racchiuso tra/*e*/viene ignorato dal compilatore).La direttiva
#include <stdio.h>. Questa riga serve a includere informazioni contenute nella libreria stdio.h (Standard Input and Output), libreria che mette a disposizione, tra le altre cose, la funzioneprintfche abbiamo usato per stampare il testo a video. Più avanti scopriremo altre librerie utilissime per i nostri progetti. Per precisione, questa riga non include una “libreria” vera e propria, ma un header file (da cui l’estensione .h), un file di testo che contiene le dichiarazioni delle funzioni messe a disposizione dalla libreria. Il codice vero e proprio della funzione, invece, verrà unito al tuo programma in un secondo momento, durante la fase di linking che abbiamo descritto poco fa.La funzione principale:
int main(void). Ogni singolo programma scritto in C deve avere una funzione principale. Questa funzione si chiamamain. L’esecuzione del tuo programma partirà da lì. Studieremo le funzioni nel dettaglio più avanti, per ora ti basta sapere che ilmainracchiude le istruzioni che il computer dovrà eseguire. La parolaintprima del nome indica che questa funzione, alla fine del suo lavoro, deve restituire un numero intero. Ilmain(come ogni altra funzione) ha quindi un nome, un valore di ritorno, eventualmente un elenco di argomenti in ingresso tra le parentesi tonde e un corpo, ovvero lo spazio in cui risiede il codice vero e proprio, delimitato dalle parentesi graffe{ }. La parolavoidindica che la funzionemainnon accetta in questo caso alcun parametro (o argomento) in ingresso.La chiusura:
return 0;. L’ultima istruzione del corpo delmainèreturn 0;. Questo è il valore intero che la funzione restituisce per comunicare che tutto è andato a buon fine. Se ometti questa riga il programma funzionerà comunque, ma scoprirai presto che non si tratta di un aspetto estetico. Per la sola funzionemain, lo standard del linguaggio (dal C99 in poi) stabilisce che, se ometti ilreturn, il programma restituisce comunque 0 in automatico.
Una piccola nota: il simbolo \n in coda rappresenta un ritorno a capo e serve a far ripartire il prompt del terminale su una riga nuova. Ne riparleremo a breve.
Il C è un linguaggio standardizzato che si è evoluto nel tempo attraverso diverse versioni (C89, C99, C11, C17, C23). In questa dispensa facciamo riferimento al C moderno (dal C99 in poi), che è quello supportato senza configurazioni particolari da tutti i compilatori attuali.