#define è una direttiva del preprocessore che sostituisce semplicemente tutte le occorrenze dell'identificatore con il valore prima della compilazione. Non crea variabili, non conosce i tipi, non verifica i limiti e non rispetta l'ambito.
const è un qualificatore che crea una vera variabile, ma bloccata in scrittura dopo l'inizializzazione. Una variabile const ha un tipo, un ambito, partecipa al debugging e può essere più sicura. Queste variabili vengono allocate nella sezione .rodata o nello stack/in memoria.
#define — per valori scalari semplici necessari in fase di compilazione, specialmente se utilizzati in condizioni del preprocessore o dimensioni di array (#define SIZE 16).const — per valori che devono essere passati in modo sicuro dal punto di vista dei tipi, debuggati e in modo sicuro esportati (nei file di intestazione, tra moduli).const.Esempio:
#define PI 3.14159 const double G = 9.81; int arr[PI]; // ERRORE! PI non è un intero int arr2[G]; // ERRORE! G non è un valore di tempo di compilazione
Domanda: Funziona const int a = 10; come costante di tempo di compilazione per creare un array: int arr[a];?
Risposta: No. Nel linguaggio C const è un qualificatore, ma la variabile viene creata e inizializzata durante l'esecuzione, e non durante la compilazione, quindi la dimensione dell'array deve essere un letterale o un'espressione nota al compilatore. Utilizzare #define, oppure enum { SIZE = 10 };.
Esempio di errore:
const int a = 5; int arr[a]; // In C89/90 non funzionerà (VLA sono apparsi in C99, ma non ovunque)
Storia
Nel media server si è tentato di utilizzare
const intper impostare le dimensioni del buffer, pensando che fosse una "costante di tempo di compilazione". Su un compilatore (GCC, C99) tutto funzionava, ma su molti altri c'era un errore di compilazione (VLA non supportati), si è dovuto riscrivere urgentemente con #define.
Storia
In codice dipendente dalla piattaforma, si è definita una stringa tramite
#define NAME "MyApp", utilizzata in più punti e dimenticata di metterla tra parentesi. Dopo l'aggiunta di caratteri alla stringa senza esplicite parentesi si ottenevano risultati sbagliati, portando a bug strani nei log.
Storia
In un progetto con più moduli, si è definita una costante tramite #define in due punti con valori diversi (copia e incolla). Il risultato — i moduli lavoravano con costanti diverse, portando a non conformità dei dati, correggibili solo con un attento debugging.