Il tutorial completo per imparare il linguaggio C da zero: il โpadreโ di tanti linguaggi moderni, veloce e vicino alla macchina. Esempi spiegati passo passo.
Introduzione al linguaggio C
C รจ un linguaggio di programmazione creato da Dennis Ritchie nei laboratori Bell nel 1972. ร uno dei linguaggi piรน influenti della storia: da lui derivano C++, C#, Java, JavaScript e molti altri. ร usato per sistemi operativi (Linux, Windows), driver, sistemi embedded, microcontrollori e tutto ciรฒ che richiede massima velocitร ed efficienza.
C รจ un linguaggio compilato, procedurale e di โbasso livelloโ rispetto ad altri: dร al programmatore il controllo diretto della memoria. ร piรน severo e tecnico, ma capirlo ti fa comprendere davvero come funziona un computer.
๐ C non si esegue nel browser: serve un compilatore (es. GCC). In questo corso gli esempi si leggono e si modificano con la sintassi colorata.
Esempio
Installare C (Get Started)
Per compilare codice C ti serve un compilatore. Il piรน diffuso รจ GCC (su Linux/macOS spesso giร presente, su Windows tramite MinGW). Come editor si usano VS Code, Code::Blocks o Dev-C++.
Terminale
Sintassi e primo programma
Ogni programma C parte dalla funzione main(). La direttiva #include importa librerie (qui stdio.h per l'input/output). Le istruzioni terminano con ; e i blocchi sono tra { }.
Esempio
Output: la funzione printf
printf() stampa testo a schermo. Usa gli specificatori di formato per inserire valori: %d (interi), %f (decimali), %c (caratteri), %s (stringhe). \n manda a capo.
Esempio
I commenti
Commenti su una riga con //, su piรน righe con /* ... */.
Esempio
Le variabili
In C ogni variabile va dichiarata con il suo tipo prima dell'uso: tipo nome = valore;.
Esempio
I tipi di dato
I tipi fondamentali di C:
Tipo
Descrizione
printf
int
Intero
%d
float / double
Decimali
%f
char
Carattere singolo
%c
char[]
Stringa
%s
C non ha un tipo booleano nativo nelle versioni storiche: si usano gli interi (0 = falso, diverso da 0 = vero) o stdbool.h.
Conversione di tipo (casting)
La conversione di tipo trasforma un valore da un tipo a un altro. Puรฒ essere implicita (automatica) o esplicita (cast manuale con (tipo)).
Esempio
๐ก La divisione tra due interi dร un intero: 7/2 = 3. Per ottenere 3.5 serve il cast a double di almeno un operando.
Le costanti
Una costante non puรฒ cambiare valore. Si dichiara con const oppure con la direttiva #define.
Esempio
Gli operatori
Aritmetici (+ - * / %), di confronto (== != > <) e logici (&& || !).
Esempio
Booleans in C
C non aveva un tipo booleano nativo fino a C99. Includendo stdbool.h si possono usare bool, true e false. Senza la libreria, 0 รจ falso e qualsiasi altro valore รจ vero.
Esempio
๐ In C i booleani sono interi: true vale 1, false vale 0. Le funzioni di confronto restituiscono questi valori.
Input: la funzione scanf
scanf() legge dati dalla tastiera. Richiede l'operatore & davanti al nome della variabile (indirizzo in memoria).
Esempio
Le condizioni: if, else if, else
Esempio
Il costrutto switch
Esempio
Il ciclo while
Esempio
Il ciclo for
Esempio
Break e Continue
break interrompe immediatamente il ciclo; continue salta all'iterazione successiva.
Esempio
Gli array
Un array contiene piรน valori dello stesso tipo, con dimensione fissa. Si accede con l'indice (da 0).
Esempio
Le stringhe
In C una stringa รจ un array di caratteri che termina con il carattere nullo '\0'. La libreria string.h offre funzioni come strlen(), strcpy(), strcat().
Esempio
Le funzioni
Una funzione raggruppa codice riutilizzabile, con un tipo di ritorno, un nome e dei parametri. Si dichiara prima del main (o con un prototipo).
Esempio
Indirizzo di memoria
Ogni variabile รจ salvata in una cella di memoria con un proprio indirizzo. L'operatore & restituisce l'indirizzo di una variabile, che si stampa con %p.
Esempio
๐ Comprendere gli indirizzi di memoria รจ il primo passo per padroneggiare i puntatori, il cuore del linguaggio C.
I puntatori
I puntatori sono la caratteristica piรน potente (e temuta) di C: una variabile che contiene l'indirizzo di memoria di un'altra variabile. Si dichiarano con * e si ottiene l'indirizzo con &.
Esempio
Parametri delle funzioni
Le funzioni ricevono dati tramite i parametri. In C il passaggio รจ per valore: la funzione riceve una copia. Per modificare l'originale si passa un puntatore (passaggio per riferimento).
Per valore vs riferimento
Scope delle variabili
Lo scope determina dove una variabile รจ visibile. Le variabili locali esistono solo nel blocco in cui sono dichiarate; le globali sono visibili ovunque.
Esempio
Dichiarazione di funzione (prototipi)
Un prototipo dichiara la firma di una funzione prima del suo uso, separando dichiarazione e definizione. Permette di definire le funzioni dopo main().
Esempio
๐ก I prototipi si raccolgono nei file header .h, mentre le definizioni stanno nei file .c: รจ la base dell'organizzazione del codice in C.
Funzioni matematiche
La libreria math.h offre funzioni matematiche avanzate. Ricorda di compilare con -lm.
Esempio
Funzioni inline
La parola chiave inline suggerisce al compilatore di inserire il corpo della funzione direttamente nel punto di chiamata, eliminando l'overhead della chiamata. Utile per funzioni piccole e frequenti.
Esempio
๐ inline รจ solo un suggerimento: il compilatore decide se applicarlo. Con l'ottimizzazione (-O2) GCC inlinea automaticamente le funzioni piccole.
Ricorsione
Una funzione ricorsiva chiama se stessa. Serve sempre un caso base che ferma la ricorsione, altrimenti si ha uno stack overflow.
Fattoriale e potenza
Puntatori a funzione
Un puntatore a funzione memorizza l'indirizzo di una funzione, permettendo di passarla come argomento o sceglierla a runtime (callback).
Esempio
Creare file in C
Si apre (creandolo) un file con fopen() in modalitร "w" (scrittura). Restituisce un puntatore FILE* da chiudere con fclose().
Esempio
Modalitร
Significato
"r"
Lettura (il file deve esistere)
"w"
Scrittura (cancella il contenuto)
"a"
Append (aggiunge in coda)
"r+"
Lettura e scrittura
Scrivere su file
Con fprintf() si scrive testo formattato in un file, esattamente come printf() su schermo.
Esempio
Leggere da file
Con fgets() si legge una riga alla volta finchรฉ non si raggiunge la fine del file (EOF).
Esempio
๐ก Controlla sempre che fopen() non restituisca NULL prima di leggere: il file potrebbe non esistere o non essere accessibile.
Le struct
Una struct raggruppa piรน variabili (anche di tipo diverso) in un unico tipo personalizzato: รจ l'antenato degli oggetti.
Esempio
Struct annidate
Una struct puรฒ contenere altre struct come campi. Utile per modellare dati gerarchici (es. uno studente che contiene una data).
Esempio
Struct e puntatori
Con un puntatore a struct si accede ai campi con l'operatore freccia -> invece del punto. ร il modo piรน efficiente per passare struct alle funzioni.
Esempio
Union
Una union รจ simile a una struct, ma tutti i campi condividono la stessa area di memoria. Occupa lo spazio del campo piรน grande e puรฒ contenere un solo valore alla volta.
Esempio
๐ Differenza chiave: in una struct ogni campo ha la sua memoria; in una union condividono lo stesso spazio.
typedef
typedef crea un alias (un nuovo nome) per un tipo esistente. Si usa spesso per semplificare la sintassi delle struct.
Esempio
Enum
Un enum definisce un insieme di costanti intere con nomi leggibili. Per default partono da 0 e incrementano di 1.
Esempio
La gestione della memoria
In C il programmatore puรฒ allocare memoria dinamicamente con malloc() e liberarla con free() (libreria stdlib.h). ร potente ma rischioso: dimenticare free() causa memory leak.
Esempio
Gestione errori in C
C non ha le eccezioni: gli errori si gestiscono controllando i valori di ritorno delle funzioni e la variabile globale errno (libreria errno.h).
Esempio
๐ก Convenzione C: una funzione restituisce 0 in caso di successo e un valore diverso da zero in caso di errore.
Debugging in C
Il debugging individua e corregge gli errori. In C gli strumenti principali sono printf di controllo, il debugger GDB e l'analizzatore di memoria Valgrind.
Errori di compilazione: segnalati da GCC (sintassi, tipi)
Errori a runtime: segmentation fault, accessi a memoria non valida
Memory leak: memoria allocata e mai liberata (rilevati da Valgrind)
๐ก Compila con gcc -g -Wall programma.c: -g abilita il debug con GDB, -Wall mostra tutti gli avvisi. Poi avvia valgrind ./a.out per scovare i memory leak.
NULL e puntatori nulli
NULL รจ un puntatore speciale che non punta a nulla. Si usa per indicare "nessun valore" e va sempre controllato prima di dereferenziare un puntatore.
Esempio
โ ๏ธ Dereferenziare un puntatore NULL (es. *p quando p == NULL) causa un segmentation fault, il crash piรน comune in C.
Validazione dell'input
Validare l'input dell'utente previene crash e comportamenti imprevisti. scanf() restituisce il numero di valori letti correttamente: controllalo sempre.
Esempio
Data e ora
La libreria time.h fornisce funzioni per gestire data e ora di sistema.
Esempio
Numeri casuali
Le funzioni rand() e srand() (libreria stdlib.h) generano numeri pseudo-casuali. Si inizializza il seme con srand(time(NULL)).
Esempio
Macro e preprocessore
Le macro (#define) sono sostituzioni di testo effettuate dal preprocessore prima della compilazione. Si usano per costanti e piccole "funzioni".
Esempio
๐ก Metti sempre le parentesi attorno ai parametri di una macro: QUADRATO(x) come ((x)*(x)) evita errori con espressioni come QUADRATO(2+3).
Storage classes
Le storage classes definiscono durata, visibilitร e posizione in memoria delle variabili.
Classe
Descrizione
auto
Variabile locale (default), durata limitata al blocco
static
Conserva il valore tra le chiamate; visibilitร limitata al file
extern
Variabile globale dichiarata in un altro file
register
Suggerisce di tenere la variabile in un registro CPU
static in azione
Operatori bitwise
Gli operatori bitwise lavorano sui singoli bit dei numeri. Sono usati in programmazione di basso livello, embedded e ottimizzazioni.
Operatore
Nome
Esempio
&
AND
5 & 3 = 1
|
OR
5 | 3 = 7
^
XOR
5 ^ 3 = 6
~
NOT
~5 = -6
<<
Shift sinistra
5 << 1 = 10
>>
Shift destra
5 >> 1 = 2
Esempio
Esempi pratici C
Esempi reali e completi per consolidare la programmazione in C.
Numeri primi fino a N
Esempio
Ordinamento bubble sort
Esempio
Editor online C
Scrivi e leggi codice C con la sintassi colorata. Per eseguirlo installa GCC (o usa OnlineGDB), salva come programma.c e compila con gcc programma.c -o programma && ./programma.
Il tuo codice C
Quiz C โ verifica le tue conoscenze
Qual รจ la differenza tra = e ==? Risposta:= รจ l'assegnazione, == รจ il confronto di uguaglianza. Confonderli รจ un errore classico (es. if(x=5) assegna invece di confrontare).
Cosa fa l'operatore & davanti a una variabile? Risposta: Restituisce l'indirizzo di memoria della variabile. Si usa con scanf e con i puntatori.
Perchรฉ chiamare free() dopo malloc()? Risposta: Per liberare la memoria allocata dinamicamente ed evitare i memory leak. C non ha garbage collector.
Cos'รจ un segmentation fault? Risposta: Un crash causato dall'accesso a una zona di memoria non valida (es. dereferenziare NULL o uscire dai limiti di un array).
Qual รจ la differenza tra array e puntatore? Risposta: Un array รจ un blocco contiguo di memoria di dimensione fissa; un puntatore รจ una variabile che contiene un indirizzo. Il nome dell'array "decade" nell'indirizzo del primo elemento.
Esercizi C con soluzioni
Cinque esercizi con soluzione completa. Provaci prima di guardare!
Esercizio 1 โ Fattoriale
Soluzione
Esercizio 2 โ Inversione di una stringa
Soluzione
Esercizio 3 โ Massimo di un array
Soluzione
Esercizio 4 โ Conta vocali
Soluzione
Esercizio 5 โ Serie di Fibonacci
Soluzione
Sfide C
๐ข Scrivi una funzione che verifica se un numero รจ palindromo (es. 12321).
๐ก Implementa una calcolatrice con menu che usa puntatori a funzione per le operazioni.
๐ก Crea una lista concatenata (linked list) con funzioni per inserire, rimuovere e stampare i nodi.
๐ด Implementa uno stack e una coda con allocazione dinamica della memoria.
๐ด Scrivi un programma che legge un file di testo e conta parole, righe e caratteri (come il comando wc).
Progetti pratici con C
๐ฎ Gioco indovina il numero: con numeri casuali e conteggio tentativi
๐ Rubrica telefonica: con struct, file e ricerca
๐งฎ Calcolatrice scientifica: con puntatori a funzione
๐ Gestione magazzino: CRUD su file binario con struct
๐ข Convertitore di basi: decimale, binario, esadecimale
๐ Editor di testo minimale: lettura/scrittura file da terminale
Funzioni: parametri, scope, prototipi, ricorsione, puntatori a funzione
5
Struct, struct annidate, union, typedef, enum
6
Gestione memoria: malloc/free, NULL, debugging con GDB/Valgrind
7
File: creare, scrivere, leggere; gestione errori
8
Macro, storage classes, bitwise โ progetto finale
Domande da colloquio C
๐ฌ Differenza tra malloc e calloc? โ Entrambi allocano memoria; calloc la inizializza a zero e prende numero+dimensione come parametri separati.
๐ฌ Cos'รจ un dangling pointer? โ Un puntatore che punta a memoria giร liberata con free(). Per evitarlo, imposta il puntatore a NULL dopo il free.
๐ฌ Differenza tra struct e union? โ In una struct ogni campo ha la propria memoria; in una union tutti i campi condividono lo stesso spazio (dimensione = campo piรน grande).
๐ฌ Cosa significa passaggio per valore e per riferimento? โ Per valore si copia il dato (le modifiche non escono dalla funzione); con i puntatori si passa l'indirizzo, modificando l'originale.
๐ฌ Cos'รจ il preprocessore? โ Elabora le direttive #include, #define, #ifdef PRIMA della compilazione, sostituendo testo.
๐ฌ Perchรฉ C non ha garbage collector? โ Per dare al programmatore il controllo totale e massime prestazioni. La memoria va gestita manualmente con malloc/free.
๐ C รจ il linguaggio alla base di sistemi operativi, embedded, driver e di linguaggi come Python e Java. Padroneggiarlo dร fondamenta solide per tutta la programmazione.
Riferimento โ Parole chiave C
Keyword
Uso
int, char, float, double
Tipi di dato base
short, long, signed, unsigned
Modificatori di tipo
if, else, switch, case, default
Controllo condizionale
for, while, do
Cicli
break, continue, return, goto
Controllo di flusso
struct, union, enum, typedef
Tipi personalizzati
const
Valore costante
static, extern, auto, register
Storage classes
sizeof
Dimensione in byte di un tipo
void
Tipo vuoto / nessun valore
Riferimento โ <stdio.h>
Funzione
Descrizione
printf()
Stampa formattata su schermo
scanf()
Legge input formattato da tastiera
puts()
Stampa una stringa + a capo
gets() / fgets()
Legge una riga (usa fgets, sicuro)
getchar() / putchar()
Legge/scrive un singolo carattere
fopen() / fclose()
Apre / chiude un file
fprintf() / fscanf()
Scrive / legge su file
fgets() / fputs()
Legge / scrive righe su file
sprintf()
Stampa formattata in una stringa
Specificatori di formato
Specificatore
Tipo
%d
int
%f
float / double
%c
char
%s
stringa
%p
puntatore (indirizzo)
%x
esadecimale
%ld
long
Riferimento โ <string.h>
Funzione
Descrizione
Esempio
strlen()
Lunghezza stringa
strlen("C") โ 1
strcpy()
Copia una stringa
strcpy(dest, src)
strncpy()
Copia n caratteri (sicuro)
strncpy(d, s, 10)
strcat()
Concatena stringhe
strcat(s1, s2)
strcmp()
Confronta stringhe
strcmp("a","b") โ -1
strchr()
Cerca un carattere
strchr("casa",'s')
strstr()
Cerca una sottostringa
strstr("casa","sa")
strtok()
Divide in token
strtok(s, ",")
memset()
Riempie memoria con un valore
memset(a, 0, n)
memcpy()
Copia blocchi di memoria
memcpy(d, s, n)
Riferimento โ <math.h>
Funzione
Descrizione
Esempio
sqrt()
Radice quadrata
sqrt(16) โ 4.0
pow()
Potenza
pow(2,10) โ 1024
fabs()
Valore assoluto (double)
fabs(-5.5) โ 5.5
ceil()
Arrotonda per eccesso
ceil(4.1) โ 5
floor()
Arrotonda per difetto
floor(4.9) โ 4
round()
Arrotonda
round(4.5) โ 5
sin() cos() tan()
Trigonometria (radianti)
sin(0) โ 0
log() / log10()
Logaritmo naturale / base 10
log10(1000) โ 3
exp()
e elevato a x
exp(1) โ 2.718
fmod()
Resto in virgola mobile
fmod(7.5,2) โ 1.5
๐ Per usare <math.h> compila linkando la libreria matematica: gcc programma.c -lm
Certificazione C
Le certificazioni in linguaggio C sono apprezzate nei settori embedded, sistemi e sicurezza:
Certificazione
Ente
Livello
CLA โ C Programming Language Certified Associate
C++ Institute / Pearson VUE
Base/Intermedio
CLP โ C Certified Professional Programmer
C++ Institute
Avanzato
C Certification
W3Schools
Base
Come prepararsi
๐ Studia il classico The C Programming Language di Kernighan & Ritchie (il "K&R")
Hai completato il corso di C! Hai imparato la sintassi, i puntatori, le struct, la gestione manuale della memoria, i file e le funzionalitร avanzate. C รจ impegnativo ma formativo: ti dร basi solidissime per qualsiasi altro linguaggio.
E ora cosa fare?
๐ป Installa GCC (MinGW su Windows, giร presente su Linux/Mac) e compila in locale
๐ Impara GDB e Valgrind per il debug e la caccia ai memory leak
๐ Pubblica i progetti su GitHub per il tuo portfolio
๐ Passa al C++ per la programmazione a oggetti, oppure approfondisci l'embedded (Arduino, microcontrollori)
๐ Esplora la sicurezza: buffer overflow, gestione memoria sicura
๐ฏ Punta alla certificazione CLA del C++ Institute
๐ฏ La tua sfida finale
Scrivi un programma in C che legge 10 numeri in un array, li ordina dal piรน piccolo al piรน grande con una funzione separata e calcola media, massimo e minimo. Bonus: salva i risultati in un file di testo.