Menu

La libreria standard del C: una mappa degli header da conoscere

Cosa ti offre ogni header standard, cioè stdio.h, stdlib.h, string.h, math.h, time.h, ctype.h, limits.h, stdbool.h, stdint.h e assert.h, con un breve esempio funzionante per ciascuno.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Il C come linguaggio è minuscolo: tipi, operatori, controllo di flusso, funzioni, puntatori. Non sa stampare, leggere un file, confrontare una stringa o allocare memoria. Tutto questo è la libreria standard: un insieme di header che ogni implementazione conforme fornisce.

Questa pagina è una mappa. Ogni sezione dice a cosa serve un header, mostra un breve esempio funzionante e rimanda alla pagina più completa quando esiste.

stdio.h: input e output

L'header che includi per primo in quasi ogni programma. Contiene printf e scanf, il tipo FILE e le funzioni sui file, e le funzioni di input per righe più sicure.

L'essenziale: printf, fprintf, sprintf, snprintf per l'output; scanf, fscanf, sscanf, fgets, getchar per l'input; fopen, fclose, fread, fwrite, fseek per i file. Trovi approfondimenti in printf, scanf e gestione dei file.

Una regola da portarsi dietro: non usare mai gets(). Non ha modo di conoscere la dimensione del tuo buffer ed è stata rimossa dallo standard in C11. Al suo posto si usa fgets(buf, sizeof buf, stdin).

stdlib.h: utilità generali

Il contenitore di tutto: memoria, conversioni, casualità, controllo del processo, ordinamento.

Da ricordare: malloc, calloc, realloc, free (vedi memoria dinamica); atoi, atof, strtol, strtod per le conversioni, dove conviene preferire la famiglia strto*, che sa segnalare un errore mentre atoi restituisce 0 in silenzio; rand e srand (vedi numeri casuali); exit, abort, getenv, system; e qsort/bsearch.

string.h: stringhe e blocchi di memoria

Le stringhe C sono array di char che terminano con '\0', e ogni operazione su di esse è una chiamata di funzione.

Due abitudini evitano che questo header diventi una fonte di buffer overflow: conosci sempre la dimensione della destinazione, e ricorda che strcmp restituisce 0 quando le stringhe sono uguali, quindi if (strcmp(a, b)) è vero quando le stringhe sono diverse. Le funzioni sulle stringhe trattano nel dettaglio gli schemi più sicuri con strncpy/snprintf.

math.h: matematica

sqrt, pow, fabs, floor, ceil, round, fmod, le famiglie trigonometriche e logaritmiche, INFINITY e NAN.

È l'unico header che può richiedere un'opzione per il linker: su Linux aggiungi -lm alla fine del comando di compilazione, altrimenti il linker segnala "undefined reference to sqrt". Il giro completo è nelle funzioni matematiche.

time.h: orologi e date

I due scostamenti di struct tm fregano tutti: tm_year conta dal 1900 e tm_mon parte da 0. time(NULL) è anche il seme abituale per srand.

ctype.h: classificazione dei caratteri

Piccolo, e più utile di quanto sembri. Ogni funzione riceve un carattere e risponde a una domanda sì/no, oppure converte maiuscole e minuscole.

L'insieme completo: isalpha, isdigit, isalnum, isspace, isupper, islower, ispunct, isxdigit, isprint, più toupper e tolower.

Nota il cast (unsigned char). Queste funzioni sono definite per i valori rappresentabili come unsigned char più EOF; un char semplice ha il segno sulla maggior parte dei sistemi, quindi un byte sopra 127 arriva come numero negativo e la chiamata diventa comportamento indefinito. Il cast non costa nulla ed elimina l'intera categoria di problemi.

E preferisci queste funzioni ai controlli fatti a mano. c >= '0' && c <= '9' per caso funziona, ma isdigit(c) dice quello che intendi e resta corretto ovunque.

limits.h e float.h: i confini dei tipi

Quanto può diventare grande un int su questa macchina? Questi header rispondono, e le risposte sono il motivo per cui il codice portabile chiede invece di presumere.

INT_MAX è il modo per controllare l'overflow prima che avvenga, ed è importante perché l'overflow con segno è comportamento indefinito, non un giro a capo che puoi verificare dopo.

stdbool.h e stdint.h: tipi migliori

Il C non ha avuto un tipo booleano fino al C99. <stdbool.h> ne fornisce uno:

bool, true e false sono macro per _Bool, 1 e 0, ma rendono evidente l'intenzione. (In C23 sono diventate parole chiave e l'header non è più necessario.)

<stdint.h> fornisce tipi con larghezza garantita, essenziali per formati di file, protocolli di rete e tutto ciò che è embedded, dove "un int probabilmente è a 32 bit" non basta:

Le macro in stile PRId32 di <inttypes.h> si espandono nello specificatore printf corretto per ogni tipo a larghezza fissa sulla piattaforma corrente: è il modo portabile per stamparli, dato che %d è giusto per int32_t su alcuni sistemi e sbagliato su altri.

assert.h: verificare le tue ipotesi

assert(expr) non fa nulla quando l'espressione è vera e termina il programma con un messaggio quando è falsa.

Compilare con -DNDEBUG rimuove tutte le asserzioni, quindi in una build di rilascio non costano nulla. Ed è proprio questo l'avvertimento: non mettere mai un effetto collaterale dentro un assert. assert(read_next() > 0) nella build di rilascio smette del tutto di leggere, e il bug risultante compare solo in produzione.

Le asserzioni servono per i tuoi errori: condizioni che dovrebbero essere impossibili se il codice è corretto. Un input utente sbagliato non è un'asserzione; è un if con un messaggio di errore.

Il resto, in breve

  • <stddef.h>: size_t, ptrdiff_t, NULL, offsetof
  • <stdarg.h>: funzioni variadiche, il meccanismo dietro printf
  • <errno.h>: errno più perror e strerror per riportare perché una chiamata è fallita
  • <signal.h>: gestione dei segnali come Ctrl-C
  • <setjmp.h>: salti non locali; raramente la risposta giusta
  • <locale.h>, <wchar.h>, <wctype.h>: locale e caratteri estesi
  • <stdnoreturn.h>, <stdalign.h>, <threads.h>, <stdatomic.h>: aggiunte del C11

Due abitudini rendono piacevole usare la libreria. Leggi la pagina di manuale prima di tirare a indovinare una firma: man 3 strtol su macOS e Linux è autorevole e veloce. E controlla i valori di ritorno: malloc, fopen e strtol segnalano tutti gli errori, e un programma che li ignora fallisce molto più tardi e in modo molto meno chiaro.

Domande frequenti

Cos'è la libreria standard del C?

L'insieme di funzioni, tipi e macro che ogni implementazione conforme del C fornisce, raggruppato in circa 30 header. Copre input e output (<stdio.h>), memoria e conversioni (<stdlib.h>), stringhe (<string.h>), matematica (<math.h>), tempo, classificazione dei caratteri e limiti dei tipi numerici. Il C non ha I/O né gestione delle stringhe integrati: arriva tutto da qui.

Qual è la differenza tra stdio.h e stdlib.h?

<stdio.h> è input e output: printf, scanf, fopen, fgets, FILE. <stdlib.h> sono utilità generali: malloc e free, atoi e strtol, rand e srand, exit, qsort, bsearch. Un programma tipico li include entrambi.

A cosa serve ctype.h?

Classifica e converte singoli caratteri: isdigit, isalpha, isalnum, isspace, isupper, islower, ispunct, più toupper e tolower. Usarle invece di confronti scritti a mano come c >= '0' && c <= '9' è più chiaro e corretto per ogni locale e set di caratteri.

Devo collegare qualcosa per usare la libreria standard del C?

No, con un'eccezione: le funzioni matematiche. La libreria standard del C viene collegata automaticamente, ma su Linux le implementazioni di <math.h> stanno in una libreria separata, quindi sqrt e simili richiedono -lm alla fine del comando di compilazione. Per tutto il resto basta l'#include giusto.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA