Skip to content

Asserzioni Statiche e a Runtime

Un’asserzione è una funzione logica (predicato) che esprime una condizione che deve obbligatoriamente essere vera in un determinato punto del programma. Se la condizione si rivela falsa, significa che le assunzioni del programmatore erano errate e c’è un bug grave.

Il C offre due tipi principali di asserzioni, entrambe definite nella libreria <assert.h>.

Asserzioni a Tempo di Compilazione (static_assert)

Section titled “Asserzioni a Tempo di Compilazione (static_assert)”

La macro static_assert ti permette di bloccare la compilazione se una condizione matematica o dimensionale non è rispettata. Siccome viene valutata dal compilatore, non ha alcun impatto sulle prestazioni del programma in esecuzione.

#include <assert.h>
struct Giocatore {
unsigned int id;
char* nome;
};
// Verifica che il puntatore sia grande esattamente 8 byte (architettura a 64 bit)
static_assert(sizeof(char*) == 8, "Il programma deve essere compilato a 64-bit!");

Se provi a compilare questo codice su un sistema a 32-bit (dove i puntatori occupano 4 byte), la compilazione fallirà istantaneamente mostrando il messaggio personalizzato!

La macro assert() inietta controlli diagnostici che avvengono durante l’esecuzione del programma. Se l’espressione valutata è falsa (pari a 0), l’asserzione stampa su stderr il nome del file, la linea di codice esatta e l’espressione fallita, per poi chiamare la funzione abort() e far crashare volontariamente il programma.

#include <assert.h>
#include <stddef.h>
void duplica_stringa(size_t dimensione, char *str) {
// Il programmatore assume che il chiamante non passi mai un puntatore NULL
assert(str != NULL && "Errore fatale: il chiamante ha passato NULL!");
// ... logica ...
}

Trucco: Nota come possiamo concatenare un messaggio testuale usando && "messaggio". Essendo una stringa letterale, il puntatore non è mai nullo e quindi non altera la validità logica del test (True AND True = True).

Prima di distribuire il programma finito, le asserzioni a runtime vanno disabilitate. Basta passare il flag -DNDEBUG al compilatore o definire la macro NDEBUG (No Debug):

#define NDEBUG
#include <assert.h> // Ora tutti gli assert() nel file verranno ignorati dal compilatore

Usa un assert per assicurarti che la velocità dell’automobile non diventi mai negativa prima di calcolare i tempi di arrivo.