EDIT: microtherion fornisce una risposta eccellente che corregge alcuni dei miei punti qui, in particolare sull'utilizzo della memoria.
Come hai identificato, ci sono alcune situazioni in cui sei costretto a usare a #define
, perché il compilatore non consente una const
variabile. Allo stesso modo, in alcune situazioni sei costretto a usare variabili, come quando hai bisogno di una matrice di valori (cioè non puoi avere una matrice di #define
).
Tuttavia, ci sono molte altre situazioni in cui non esiste necessariamente un'unica risposta "corretta". Ecco alcune linee guida che seguirei:
Sicurezza del tipo
Da un punto di vista generale della programmazione, le const
variabili sono generalmente preferibili (ove possibile). Il motivo principale è la sicurezza dei tipi.
Una #define
(macro preprocessore) copia direttamente il valore letterale in ogni posizione nel codice, rendendo indipendente ogni utilizzo. Ciò può provocare ipoteticamente ambiguità, perché il tipo potrebbe finire per essere risolto in modo diverso a seconda di come / dove viene utilizzato.
Una const
variabile è sempre e solo un tipo, che è determinato dalla sua dichiarazione e risolto durante l'inizializzazione. Richiederà spesso un cast esplicito prima che si comporti in modo diverso (anche se ci sono varie situazioni in cui può essere tranquillamente promosso implicitamente il tipo). Per lo meno, il compilatore può (se configurato correttamente) emettere un avviso più affidabile quando si verifica un problema di tipo.
Una possibile soluzione per questo è includere un cast esplicito o un suffisso di tipo in a #define
. Per esempio:
#define THE_ANSWER (int8_t)42
#define NOT_QUITE_PI 3.14f
Tale approccio può potenzialmente causare problemi di sintassi in alcuni casi, a seconda di come viene utilizzato.
Uso della memoria
A differenza dell'elaborazione per scopi generici, la memoria è ovviamente un vantaggio quando si tratta di qualcosa come un Arduino. L'uso di una const
variabile rispetto a a #define
può influire sulla posizione in cui i dati sono archiviati, il che potrebbe costringerti a utilizzare l'uno o l'altro.
const
le variabili verranno (di solito) archiviate in SRAM, insieme a tutte le altre variabili.
- I valori letterali utilizzati
#define
verranno spesso memorizzati nello spazio del programma (memoria Flash), accanto allo schizzo stesso.
(Notare che ci sono varie cose che possono influenzare esattamente come e dove viene archiviato qualcosa, come la configurazione e l'ottimizzazione del compilatore.)
SRAM e Flash hanno limitazioni diverse (ad es. 2 KB e 32 KB rispettivamente per Uno). Per alcune applicazioni, è abbastanza facile rimanere senza SRAM, quindi può essere utile spostare alcune cose in Flash. È anche possibile il contrario, sebbene probabilmente meno comune.
PROGMEM
È possibile ottenere i vantaggi della sicurezza dei tipi memorizzando anche i dati nello spazio del programma (Flash). Questo viene fatto usando la PROGMEM
parola chiave. Non funziona per tutti i tipi, ma è comunemente usato per array di numeri interi o stringhe.
Il modulo generale riportato nella documentazione è il seguente:
dataType variableName[] PROGMEM = {dataInt0, dataInt1, dataInt3...};
Le tabelle di stringhe sono un po 'più complicate, ma la documentazione ha tutti i dettagli.